在 where 子句中使用计算列
Posted
技术标签:
【中文标题】在 where 子句中使用计算列【英文标题】:Use a calculated column in a where clause 【发布时间】:2015-02-14 16:34:01 【问题描述】:我正在尝试。
我已经尝试了从 CROSS APPLY 到子查询选择的所有方法,但它没有给我任何我需要的东西。
到目前为止我的查询:
SELECT p.Code, c.AccountNumber, Sales = (SUM(p.UnitPrice) * SUM(od.QtyShipped)) FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
WHERE Sales > 100
GROUP BY p.Code, c.AccountNumber, Sales
这不起作用,因为“销售”是无效列
【问题讨论】:
你能用HAVING (SUM(p.UnitPrice) * SUM(od.QtyShipped)) > 100
代替WHERE
吗? (见w3schools.com/sql/sql_having.asp)
【参考方案1】:
在谓词中使用派生列
您需要将内部查询包装在派生表或 CTE 中,以便能够在 WHERE
子句中使用派生列(另外,请注意 SUM()
仅指定一次,使用乘法):
SELECT x.Code, x.AccountNumber, x.Sales
FROM
(
SELECT p.Code, c.AccountNumber, SUM(p.UnitPrice *od.QtyShipped) AS Sales
FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
GROUP BY p.Code, c.AccountNumber
) AS x
WHERE x.Sales > 100;
在 HAVING 子句中重复派生列
根据@Jonny 的评论,另一种方法不是干燥计算的列,而是重复计算。在应用了GROUP BY
之后,使用HAVING
而不是WHERE
。
SELECT p.Code, c.AccountNumber, SUM(p.UnitPrice *od.QtyShipped) AS Sales
FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
GROUP BY p.Code, c.AccountNumber
HAVING SUM(p.UnitPrice * od.QtyShipped) > 100;
在任何一种情况下,根据下面的 cmets,请注意计算的表达式是 SUM(p.UnitPrice * od.QtyShipped)
而不是 SUM(p.UnitPrice) * SUM(od.QtyShipped)
。
【讨论】:
嗨斯图尔特,我得到:消息 130,级别 15,状态 1,第 4 行无法对包含聚合或子查询的表达式执行聚合函数。 sql 不是我的东西,所以不知道这条消息是什么意思:$ 销售计算应该是这样的:SUM(p.UnitPrice * od.QtyShipped)
我明白你做了什么,谢谢。所以我也在学习:)。谢谢。【参考方案2】:
如果是计算列,您可以使用“HAVING”。
SELECT p.Code, c.AccountNumber, Sales = (SUM(p.UnitPrice) * SUM(od.QtyShipped)) FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
GROUP BY p.Code, c.AccountNumber, Sales
HAVING SALES > 100;
【讨论】:
很遗憾,不是。您可以在ORDER BY
中使用列别名,但不能在 HAVING
中使用 - 您需要在 HAVING 中重复完整的计算(如 @Jonny 的评论),或者包装计算列。 Demo Here【参考方案3】:
您可以为此使用公用表表达式
;WITH CTE AS
(
SELECT p.Code, c.AccountNumber, Sales = (SUM(p.UnitPrice) * SUM(od.QtyShipped)) FROM [dbo].Customer c
LEFT JOIN [dbo].OrderHeader oh ON oh.CustomerId = c.Id
LEFT JOIN [dbo].OrderDetail od ON od.OrderHeaderId = oh.Id
LEFT JOIN [dbo].Product p ON p.Id = od.ProductId
GROUP BY p.Code, c.AccountNumber, Sale
)
SELECT *
FROM CTE WHERE CTE.Sales>100
【讨论】:
以上是关于在 where 子句中使用计算列的主要内容,如果未能解决你的问题,请参考以下文章
在 BigQuery 中,带有空值数组列的“where”子句导致问题
不使用`where`子句,但得到错误:“未知列 在where子句中“