在select语句中将连接查询重新声明为相关子查询

时间:2013-02-16 22:52:11

标签: sql sql-server-2008

作为练习作业,我希望在select子句中将连接重写为子查询。我知道select语句中的子查询必须返回一个值,而我很难弄清楚如何以一种有意义的方式重写它。

这是原始的连接声明:

SELECT InvoiceNumber, InvoiceDate, InvoiceLineItemAmount
FROM Invoices JOIN InvoiceLineItems
  ON Invoices.InvoiceID = Invoicelineitems.InvoiceID
WHERE VendorID = 122
ORDER BY InvoiceDate

非常感谢任何提示或帮助!

3 个答案:

答案 0 :(得分:1)

我的建议是在主查询中使用InvoiceLineItem,在子查询中使用发票。这将增加让子查询返回一行的可能性。

答案 1 :(得分:1)

您只需将条件放在子查询的ON子句中,而不是使用WHERE子句。

SELECT InvoiceNumber, InvoiceDate,
       (SELECT InvoiceLineItemAmount
        FROM InvoiceLineItems
        WHERE Invoices.InvoiceID = Invoicelineitems.InvoiceID)
          AS InvoiceLineItemAmount
FROM Invoices
WHERE VendorID = 122
ORDER BY InvoiceDate

如果您的子查询返回多个值,那么您有几个选项。

您可以抓住TOP 1

SELECT InvoiceNumber, InvoiceDate,
       (SELECT TOP 1 InvoiceLineItemAmount
        FROM InvoiceLineItems
        WHERE Invoices.InvoiceID = Invoicelineitems.InvoiceID)
          AS InvoiceLineItemAmount
FROM Invoices
WHERE VendorID = 122
ORDER BY InvoiceDate

您可以使用聚合函数

SELECT InvoiceNumber, InvoiceDate,
       (SELECT MAX(InvoiceLineItemAmount)
        FROM InvoiceLineItems
        WHERE Invoices.InvoiceID = Invoicelineitems.InvoiceID)
          AS InvoiceLineItemAmount
FROM Invoices
WHERE VendorID = 122
ORDER BY InvoiceDate

或者您可以使用XML

连接结果
SELECT InvoiceNumber, InvoiceDate,
       STUFF((
           SELECT ', ' + LTRIM(InvoiceLineItemAmount)
           FROM InvoiceLineItems
           WHERE Invoices.InvoiceID = Invoicelineitems.InvoiceID
           FOR XML PATH('')),
           1, 2, '') AS InvoiceLineItemAmount
FROM Invoices
WHERE VendorID = 122
ORDER BY InvoiceDate

或者,对于@MartinSmith,您可以反转关系并挂起InvoiceLineItems。但是,如果不知道您的架构限制,您可能会遇到相同的returns more than one value问题。

SELECT (SELECT InvoiceNumber
        FROM InvoiceLineItems
        WHERE Invoices.InvoiceID = Invoicelineitems.InvoiceID)
            AS InvoiceNumber,
       (SELECT InvoiceDate
        FROM InvoiceLineItems
        WHERE Invoices.InvoiceID = Invoicelineitems.InvoiceID)
            AS InvoiceDate
       InvoiceLineItemAmount
FROM InvoiceLineItems
WHERE VendorID = 122
ORDER BY InvoiceDate

最终,这一切都取决于您的要求。

答案 2 :(得分:0)

如果在子查询中有多行,则需要TOP子句

SELECT InvoiceNumber, InvoiceDate, 
 (
  SELECT InvoiceLineItemAmount
  FROM InvoiceLineItems
  WHERE Invoices.InvoiceID = Invoicelineitems.InvoiceID
  ) AS InvoiceLineItemAmount 
FROM Invoices
WHERE VendorID = 122
ORDER BY InvoiceDate