2009-02-24 12 views
77

So che posso selezionare una colonna da una sottoquery utilizzando questa sintassi:Come posso selezionare più colonne da una sottoquery (in SQL Server) che dovrebbe avere un record (selezionare 1 in alto) per ogni record nella query principale?

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' 

Ma qual è la sintassi corretta da utilizzare più colonne da una subquery (nel mio caso un prescelto top 1 subquery)? Grazie mille.

risposta

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

Non solo questa risposta non è spiegato a tutti, c'è anche alcuna relazione tra i tavoli. Come può avere così tanti voti? –

+3

Per favore, spiega cosa stai facendo lì, grazie. – BastetFurry

7

Dovrete fare un join:

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' 

, assumendo che b.id è un PRIMARY KEY su B

In MS SQL 2005 e superiori è possibile utilizzare la seguente sintassi:

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 

Questo selezionerà esattamente un reco da B per ogni SalesOrderId.

99

Ecco generalmente come selezionare più colonne da una sottoquery:

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 

Se state in ultima analisi, cercando di fare è ottenere i valori dalla riga con il valore più alto per Foo (piuttosto che il massimo di foo e il massimo di foo2 - che non è la stessa cosa), allora quanto segue di solito funziona meglio di una sottoquery:

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 

stai fondamentalmente dicendo, mi danno la riga dalla B dove non riesco a trovare qualsiasi altra riga da B con lo stesso SalesOrderID e una maggiore Foo.

0

penso che sia quello che vuoi.

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 non può essere associato – 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

Questa risposta funziona in modo ottimale quando la corrispondenza di B deve essere diversa per ciascun record A, che non funziona con un tipico join secondario. – Keith

+0

Grazie, l'applicazione esterna è migliore di unire, perché è possibile fare riferimento anche ad altri parametri, necessari per chiamate di funzioni più complesse, ecc. –

Problemi correlati