2009-02-24 7 views
77

wiem, że mogę wybrać kolumnę z podkwerendzie używając następującej składni:Jak mogę wybrać wiele kolumn z podkwerendy (w SQL Server), które powinny mieć jeden rekord (wybierz top 1) dla każdego rekordu w głównym zapytaniu?

SELECT A.SalesOrderID, A.OrderDate, 
     (
     SELECT TOP 1 B.Foo 
     FROM B 
     WHERE A.SalesOrderID = B.SalesOrderID 
     ) AS FooFromB 
FROM A 
WHERE A.Date BETWEEN '2000-1-4' AND '2010-1-4' 

Ale jaka jest poprawna składnia, aby korzystać z wielu kolumn z podzapytania (w moim przypadku select top 1 podzapytanie)? Dziękuję Ci bardzo.

Odpowiedz

2
SELECT 
    T1.PrimaryKey, 
    T1.SomeColumn, 
    MySubQuery.Col1, 
    MySubQuery.Col2, 
    MySubQuery.Col3 
From 
    Table1 T1 
    LEFT JOIN (SELECT TOP 1 Col1, Col2, Col3, Fkey FROM Table 2 ORDER BY Col1 DESC) AS MySubQuery ON T1.PrimaryKey = MySubQuery.Fkey 
+47

Nie tylko ta odpowiedź nie jest wyjaśnione w ogóle, nie ma też relacja między stolikami. Jak to możliwe, że tak wiele przebojów? –

+3

Proszę wyjaśnij, co tam robisz, dziękuję. – BastetFurry

7

Będziesz musiał dokonać złączenia:

SELECT A.SalesOrderID, B.Foo 
FROM A 
JOIN B bo ON bo.id = (
    SELECT TOP 1 id 
    FROM B bi 
    WHERE bi.SalesOrderID = a.SalesOrderID 
    ORDER BY bi.whatever 
    ) 
WHERE A.Date BETWEEN '2000-1-4' AND '2010-1-4' 

, zakładając, że b.id jest PRIMARY KEY na B

W MS SQL 2005 i wyżej można użyć następującej składni:

SELECT SalesOrderID, Foo 
FROM (
    SELECT A.SalesOrderId, B.Foo, 
     ROW_NUMBER() OVER (PARTITION BY B.SalesOrderId ORDER BY B.whatever) AS rn 
    FROM A 
    JOIN B ON B.SalesOrderID = A.SalesOrderID 
    WHERE A.Date BETWEEN '2000-1-4' AND '2010-1-4' 
) i 
WHERE rn 

Spowoduje to wybranie dokładnie jednego reco rd od B dla każdego SalesOrderId.

99

Oto ogólnie jak wybrać wiele kolumn z podzapytania:

SELECT 
    A.SalesOrderID, 
    A.OrderDate, 
    SQ.Max_Foo, 
    SQ.Max_Foo2 
FROM 
    A 
LEFT OUTER JOIN 
    (
    SELECT 
      B.SalesOrderID, 
      MAX(B.Foo) AS Max_Foo, 
      MAX(B.Foo2) AS Max_Foo2 
    FROM 
      B 
    GROUP BY 
      B.SalesOrderID 
    ) AS SQ ON SQ.SalesOrderID = A.SalesOrderID 

razie czego ostatecznie staramy się robić to uzyskać wartości z wiersza o najwyższej wartości dla Foo (zamiast max foo i max foo2 - co nie jest to samo), a następnie dodaje się zwykle działają lepiej niż podkwerendzie:

SELECT 
    A.SalesOrderID, 
    A.OrderDate, 
    B1.Foo, 
    B1.Foo2 
FROM 
    A 
LEFT OUTER JOIN B AS B1 ON 
    B1.SalesOrderID = A.SalesOrderID 
LEFT OUTER JOIN B AS B2 ON 
    B2.SalesOrderID = A.SalesOrderID AND 
    B2.Foo > B1.Foo 
WHERE 
    B2.SalesOrderID IS NULL 

jesteś w zasadzie mówiąc: Daj mi wiersz z B, gdzie nie mogę znaleźć dowolny inny wiersz z B z tym samym SalesOrderID i większym Foo.

0

Myślę, że to jest to, czego chcesz.

SELECT 
     A.SalesOrderID, 
     A.OrderDate, 
     FooFromB.* 

FROM A, 
    (SELECT TOP 1 B.Foo 
     FROM B 
     WHERE A.SalesOrderID = B.SalesOrderID 
    ) AS FooFromB 

WHERE A.Date BETWEEN '2000-1-4' AND '2010-1-4' 
+1

A.SalesOrderID nie może być powiązany – Patrick

6
SELECT a.salesorderid, a.orderdate, s.orderdate, s.salesorderid 
FROM A a 
OUTER APPLY (SELECT top(1) * 
      FROM B b WHERE a.salesorderid = b.salesorderid) as s 
WHERE A.Date BETWEEN '2000-1-4' AND '2010-1-4' 
+0

Ta odpowiedź działa świetnie, gdy dopasowanie z B musi się różnić dla każdego rekordu A, który nie działa z typowym łączeniem podkwerendy. – Keith

+0

Dziękuję, zastosowanie zewnętrzne jest lepsze niż sprzężenie, ponieważ można odwoływać się do innych parametrów, co jest potrzebne w przypadku bardziej złożonych wywołań funkcji itp. –

Powiązane problemy