SELECT logcount, logUserID, maxlogtm
, DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
WHERE daysdiff > 120
我得到“无效的列名daysdiff”。
Maxlogtm是日期时间字段。是让我发疯的小东西。
#1 楼
SELECT
logcount, logUserID, maxlogtm,
DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
WHERE ( DATEDIFF(day, maxlogtm, GETDATE() > 120)
通常,您不能在
WHERE
子句中引用字段别名。 (将其视为包括别名在内的整个SELECT
应用于WHERE
子句之后。)但是,如其他答案所述,您可以强制SQL将SELECT
视为在WHERE
子句之前进行处理。通常使用圆括号来强制操作的逻辑顺序,或者使用通用表表达式(CTE):括号/子选择:
SELECT
*
FROM
(
SELECT
logcount, logUserID, maxlogtm,
DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
) as innerTable
WHERE daysdiff > 120
或查看亚当的CTE版本答案。
评论
这不可能直接实现,因为按时间顺序,WHERE发生在SELECT之前,这始终是执行链中的最后一步。参考-stackoverflow.com/questions/356675/…
–大卫·布莱恩
2012-12-21在1:26
afaik如果选择中的别名是相关子查询,则它将起作用,而CTE解决方案则无效。
–拉兹万·弗拉维斯·熊猫(RăzvanFlavius Panda)
16年5月31日在9:15
正如Pascal在此处的stackoverflow.com/a/38822328/282887回答中所提到的,您可以使用HAVING子句,该子句的运行速度似乎比子查询快。
–巴赫蒂奥尔
19 Mar 26 '19在8:06
@Bakhtiyor HAVING答案不适用于大多数SQL环境,包括此问题所涉及的MS-SQL。 (在T-SQL中,HAVING需要聚合函数。)
–杰米F
19 Mar 26 '19 at 13:45
#2 楼
如果要在WHERE
子句中使用别名,则需要将其包装在子select或CTE中:WITH LogDateDiff AS
(
SELECT logcount, logUserID, maxlogtm
, DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
)
SELECT logCount, logUserId, maxlogtm, daysdiff
FROM LogDateDiff
WHERE daysdiff > 120
评论
您碰巧知道这种公平的交易效率如何吗?使用CTE是否会有额外的开销?
–詹姆斯
2014年7月4日在9:20
CTE只是子查询的更漂亮语法,因此性能将与此类似。根据我的经验,性能差异并不是让我担心的事情,但在您的环境中对其进行测试应该相当简单,以查看特定的表/查询是否受到此行为的不利影响,而不是大声疾呼。公式专门在where子句中。我怀疑您不会注意到有什么不同。
–亚当·温格(Adam Wenger)
2014年7月4日在17:17
除非您尝试使用一个CTE作为子查询,否则CTE非常好。我不得不诉诸于创建它们作为嵌套它们的视图。我认为这是一个严重的SQL缺点
–共鸣器
17年8月21日在13:55
#3 楼
无需重复执行代码的最有效方法是使用HAVING而不是WHERESELECT logcount, logUserID, maxlogtm
, DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
HAVING daysdiff > 120
评论
我认为对别名使用HAVING不是标准的(尽管它确实适用于MySQL)。具体来说,我认为它不适用于SQL Server。
–托克兰
16-11-25在12:10
SQL Server:[S0001] [207]无效的列名'daysdiff'
–Vadzim
17年11月2日在17:28
SQL Server:[S0001] [8121]在“ HAVING”子句中,“ day”列无效,因为它不包含在聚合函数或GROUP BY子句中。
–Vadzim
17年11月2日在17:28
#4 楼
如果您不想在CTE中列出所有列,则另一种方法是使用outer apply
:select
s.logcount, s.logUserID, s.maxlogtm,
a.daysdiff
from statslogsummary as s
outer apply (select datediff(day, s.maxlogtm, getdate()) as daysdiff) as a
where a.daysdiff > 120
#5 楼
如何使用子查询(在Mysql中对我有用)?SELECT * from (SELECT logcount, logUserID, maxlogtm
, DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary) as 'your_alias'
WHERE daysdiff > 120
#6 楼
根据文档,HAVING在MySQL中工作:
HAVING子句已添加到SQL,因为WHERE关键字不能
与聚合函数一起使用。 >
#7 楼
您可以引用列别名,但需要使用CROSS/OUTER APPLY
进行定义:SELECT s.logcount, s.logUserID, s.maxlogtm, c.daysdiff
FROM statslogsummary s
CROSS APPLY (SELECT DATEDIFF(day, s.maxlogtm, GETDATE()) AS daysdiff) c
WHERE c.daysdiff > 120;
DBFiddle Demo
单个表达式的定义(易于维护/无需复制粘贴)
无需使用CTE /外部查询包装整个查询
可在
WHERE/GROUP BY/ORDER BY
中引用可能会有更好的性能(单次执行)
评论
值得一提的是,它仅适用于SQL Server
– Martin Zinovsky
18-10-26在13:49
@MartinZinovsky问题被标记为sql-server和t-sql :)
–卢卡斯·索佐达(Lukasz Szozda)
18-10-26在14:31
#8 楼
对我来说,在WHERE类中使用ALIAS的最简单方法是创建一个子查询并从中选择。示例:
WITH Q1 AS (
SELECT LENGTH(name) AS name_length,
id,
name
FROM any_table
)
SELECT id, name, name_length form Q1 where name_length > 0
干杯,
凯尔
#9 楼
来到这里看起来与此类似,但是带有CASE WHEN,并且最终使用了这样的位置:WHERE (CASE WHEN COLUMN1=COLUMN2 THEN '1' ELSE '0' END) = 0
也许您可以直接在DATEDIFF
中使用WHERE
。 类似的东西:
SELECT logcount, logUserID, maxlogtm
FROM statslogsummary
WHERE (DATEDIFF(day, maxlogtm, GETDATE())) > 120
评论
对于mysql不确定,但是别名可能需要用ticks`daysdiff`包装。