2009-02-24 18 views
77

Tôi biết tôi có thể chọn một cột từ một subquery sử dụng cú pháp sau:Làm cách nào tôi có thể chọn nhiều cột từ truy vấn phụ (trong SQL Server) cần có một bản ghi (chọn đầu trang 1) cho mỗi bản ghi trong truy vấn chính?

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' 

Nhưng cú pháp đúng để sử dụng nhiều cột từ một subquery (trong trường hợp của tôi một lựa chọn hàng đầu 1 subquery) là gì? Cảm ơn nhiều.

Trả lời

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

Không chỉ câu trả lời này không giải thích gì cả, đó cũng là không có mối quan hệ giữa các bảng. Làm thế nào điều này có thể có rất nhiều upvotes? –

+3

Hãy giải thích những gì bạn đang làm ở đó, cảm ơn. – BastetFurry

7

Bạn sẽ phải thực hiện một tham gia:

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' 

, giả định rằng b.id là một PRIMARY KEY trên B

Trong MS SQL 2005 và cao hơn bạn có thể sử dụng cú pháp sau:

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 

Điều này sẽ chọn chính xác một lần khôi phục thứ từ B cho mỗi SalesOrderId.

99

Dưới đây là nói chung làm thế nào để chọn nhiều cột từ một subquery:

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 

Nếu cuối cùng bạn đang cố gắng làm là lấy các giá trị từ hàng với giá trị cao nhất cho Foo (chứ không phải là tối đa foo và tối đa của foo2 - đó không phải là điều tương tự) sau đó sau thường sẽ làm việc tốt hơn so với một subquery:

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 

Bạn đang cơ bản nói, cho tôi hàng từ B, nơi tôi không thể tìm thấy bất kỳ hàng nào khác từ B có cùng SalesOrderID và Foo lớn hơn.

0

tôi nghĩ đó là những gì bạn muốn.

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 không thể bị ràng buộc – 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

Câu trả lời này hoạt động tốt khi kết quả từ B cần khác nhau cho mỗi bản ghi A, không hoạt động với một truy vấn con điển hình. – Keith

+0

Cảm ơn bạn, áp dụng bên ngoài là tốt hơn so với tham gia, bởi vì người ta có thể tham khảo các thông số khác là tốt, đó là cần thiết cho các cuộc gọi chức năng phức tạp hơn vv –

Các vấn đề liên quan