SELECT logcount, logUserID, maxlogtm
   , DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
WHERE daysdiff > 120
我得到


“无效的列名daysdiff”。


Maxlogtm是日期时间字段。是让我发疯的小东西。

评论

对于mysql不确定,但是别名可能需要用ticks`daysdiff`包装。

#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而不是WHERE

SELECT 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