2013-04-01 18 views
6

Biorąc pod uwagę następujące tabele i dane przykładowe:Czy instrukcja select może zawierać zagnieżdżone zestawy wyników?

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'); 

chciałbym się dowiedzieć, czy mogę zapytać tabeli nadrzędnej Orders a także uzyskać tabelę dziecko OrderItems jako zagnieżdżony wynik ustawiony w wyniku dominującej. Coś takiego:

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

Kwerenda mam na myśli (co nie działa w SQL Server) jest mniej więcej tak:

-- 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; 

Jest to po prostu koncepcyjne pytanie, staram myśleć o sposobach uzyskania powiązanych danych przy minimalnym powielaniu (w przeciwieństwie do tego, co by się stało z join, na przykład).

SQL Fiddle here.

UPDATE

dowiedziałem się od this answer że Oracle wspiera go z wyrażeniami kursora:

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

To byłoby sprzeczne z modelu relacyjnego (w szczególności 1NF wymóg dla atrybutu składa się z jednej rzeczywistości tylko). – Oded

+1

Jeśli potrzebujesz połączenia, powinieneś użyć jednego. Nawet jeśli masz podzapytanie do pracy, byłoby to skorelowane podzapytanie, które jest znacznie wolniejsze niż sprzężenie (skorelowane podkwerendy są uruchamiane przez wiersz i są w zasadzie kursorami i powinny być zawsze w kodzie produkcyjnym). Zwykle formatowanie takie jak powyżej pokazuje aplikacja, a nie SQL. – HLGEM

+0

@HLGEM: Formatowanie było tylko po to, aby pokazać wynik, który chciałem. "Problem" związany z "łączeniem" polega na tym, że może on przesłać znacznie więcej danych niż jest to konieczne. Powiedzmy, że tabela 'Zamówienia' ma 200 kolumn, a każde zamówienie ma średnio 10 pozycji ... –

Odpowiedz

9

No. To naprawdę nie jest to możliwe.

SQL Server nie obsługuje zagnieżdżonych stosunków i NF²

Chociaż można użyć FOR XML PATH aby ją z powrotem w sposób hierarchiczny.

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') 

Zwraca

<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> 

nie powtórzyć rodzica Orders

+0

+1 Dziękuję za odpowiedź. –

Powiązane problemy