2013-04-01 8 views
6

dato i seguenti tabelle e dati di esempio:Un'istruzione select può includere serie di risultati nidificati?

create table Orders (
    ID int not null primary key, 
    Customer nvarchar(100) not null); 

create table OrderItems (
    ID int not null primary key, 
    OrderID int not null foreign key references Orders(ID), 
    Product nvarchar(100) not null); 

insert into Orders values (1, 'John'); 
insert into Orders values (2, 'James'); 
insert into OrderItems values (1, 1, 'Guitar'); 
insert into OrderItems values (2, 1, 'Bass'); 
insert into OrderItems values (3, 2, 'Guitar'); 
insert into OrderItems values (4, 2, 'Drums'); 

vorrei sapere se posso interrogare la tabella padre Orders e anche ottenere la tabella figlio OrderItems come nidificato set di risultati nel risultato genitore. Qualcosa di simile a questo:

| ORDER.ID | ORDER.CUSTOMER | ORDER.ORDERITEMS     | 
------------------------------------------------------------------ 
|   |    | ORDERITEMS.ID | ORDERITEMS.PRODUCT | 
|   |    |------------------------------------- 
|  1 |   John |    1 |    Guitar | 
|   |    |    2 |    Bass | 
|  2 |   James |    3 |    Guitar | 
|   |    |    4 |    Drums | 

L'interrogazione che ho in mente (che non funziona in SQL Server) è qualcosa di simile:

-- doesn't work, but shows the intent to have nested result sets 
select 
    o.OrderID [Order.ID], o.Customer [Order.Customer], 
    (select 
    oi.ID [OrderItems.ID], oi.Product [OrderItems.Product] 
    from OrderItems oi where o.ID = oi.OrderID 
) [Order.OrderItems] 
from Orders o; 

Questa è solo una questione concettuale che sto cercando pensare ai modi per ottenere i dati correlati con la duplicazione minima (al contrario di ciò che accadrebbe con un join, ad esempio).

SQL Fiddle here.

UPDATE

ho scoperto da this answer che Oracle sostiene con espressioni cursore:

select 
    o.*, 
    cursor(select oi.* from OrderItems oi where o.ID = oi.OrderID) as OrderItems 
from Orders o; 
+0

che sarebbe andato contro il modello relazionale (in particolare, 1NF, l'esigenza di un attributo composto da una realtà solo). – Oded

+1

Beh, se hai bisogno di un join, dovresti usarne uno. Anche se la sottoquery funzionasse, sarebbe una sottoquery correlata che è molto più lenta di un join (le subquery correlate vengono eseguite in base alla riga e sono essenzialmente dei cursori e raramente dovrebbero mai essere nel codice di produzione). Normalmente la formattazione come si mostra sopra verrà eseguita dall'applicazione non dall'SQL. – HLGEM

+0

@HLGEM: la formattazione era solo per mostrare il risultato che volevo. Il "problema" con "join" è che può trasferire molti più dati del necessario. Dì che la tabella 'Orders' ha 200 colonne, e ogni ordine ha in media 10 articoli ... –

risposta

9

No. Questo non è davvero possibile.

SQL Server non ha il supporto per le relazioni nidificate e NF²

Anche se si potrebbe usare FOR XML PATH per riportarlo in modo gerarchico.

SELECT ID  AS [@ID], 
     Customer AS [@Customer], 
     (SELECT ID  AS [@ID], 
       OrderID AS [@OrderID], 
       Product AS [@Product] 
     FROM OrderItems 
     WHERE OrderItems.OrderID = o.ID 
     FOR XML PATH('OrderItems'), TYPE) 
FROM Orders o 
FOR XML PATH('Order'), ROOT('Orders') 

Returns

<Orders> 
     <Order ID="1" Customer="John"> 
     <OrderItems ID="1" OrderID="1" Product="Guitar" /> 
     <OrderItems ID="2" OrderID="1" Product="Bass" /> 
     </Order> 
     <Order ID="2" Customer="James"> 
     <OrderItems ID="3" OrderID="2" Product="Guitar" /> 
     <OrderItems ID="4" OrderID="2" Product="Drums" /> 
     </Order> 
    </Orders> 

Questo non ripete il genitore Orders

+0

+1 Grazie per la risposta. –

Problemi correlati