sql - WHERE 子句中的引用别名(在 SELECT 中计算)

标签 sql sql-server tsql

SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE BalanceDue > 0 --error

在选定列的列表中设置为变量的计算值 BalanceDue 不能在 WHERE 子句中使用。

有什么办法可以实现吗?在这个相关问题( Using a variable in MySQL Select Statment in a Where Clause )中,答案似乎是,实际上,不,您只需写出计算(在查询中执行该计算)两次,其中没有一个很满意。

最佳答案

除了 ORDER BY 之外,您不能引用别名,因为 SELECT 是计算的倒数第二个子句。两种解决方法:

SELECT BalanceDue FROM (
  SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
  FROM Invoices
) AS x
WHERE BalanceDue > 0;

或者只是重复表达式:

SELECT (InvoiceTotal - PaymentTotal - CreditTotal) AS BalanceDue
FROM Invoices
WHERE  (InvoiceTotal - PaymentTotal - CreditTotal)  > 0;

我更喜欢后者。如果表达式极其复杂(或计算成本高昂),您可能应该考虑使用计算列(并且可能是持久化的),特别是当大量查询引用同一表达式时。

PS你的担心似乎没有根据。至少在这个简单的例子中,SQL Server 足够聪明,只执行一次计算,即使您已经引用了两次。继续比较计划;你会发现它们是相同的。如果您遇到更复杂的情况,即多次计算表达式,请发布更复杂的查询和计划。

下面是 5 个示例查询,它们都产生完全相同的执行计划:

SELECT LEN(name) + column_id AS x
FROM sys.all_columns
WHERE LEN(name) + column_id > 30;

SELECT x FROM (
SELECT LEN(name) + column_id AS x
FROM sys.all_columns
) AS x
WHERE x > 30;

SELECT LEN(name) + column_id AS x
FROM sys.all_columns
WHERE column_id + LEN(name) > 30;

SELECT name, column_id, x FROM (
SELECT name, column_id, LEN(name) + column_id AS x
FROM sys.all_columns
) AS x
WHERE x > 30;

SELECT name, column_id, x FROM (
SELECT name, column_id, LEN(name) + column_id AS x
FROM sys.all_columns
) AS x
WHERE LEN(name) + column_id > 30;

所有五个查询的结果计划:

enter image description here

关于sql - WHERE 子句中的引用别名(在 SELECT 中计算),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11182339/

相关文章:

mysql - 使用逻辑 ER 的 SQL 数据库设计

c# - 如何从特定单词中删除部分字符串?

SQL:合并重叠的日期范围

mysql - 对多个组进行分组的 SQL 查询

mysql - 在mysql中使用group by选择最小值

mysql - 左连接或条件执行缓慢

php echo来自mysql和日期时间选择的结果

sql-server - 存储过程 OUT 参数始终返回 NULL

tsql - SQL Server 2005 用 0 填充数据透视表

sql - 从 asp 中错误的 mysql 格式日期生成 json