在 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子句中“

如何在 where 子句中使用临时列

7_mysql查询之where子句

在 WHERE 子句中使用 SQL 2005 中的命名自定义列?

SQL语句中,子句不能使用列别名问题