【问题标题】:Referring to a Column Alias in a WHERE Clause在 WHERE 子句中引用列别名
【发布时间】:2012-01-12 07:06:29
【问题描述】:
SELECT logcount, logUserID, maxlogtm
   , DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
WHERE daysdiff > 120

我明白了

“无效的列名 daysdiff”。

Maxlogtm 是一个日期时间字段。正是这些小事让我抓狂。

【问题讨论】:

  • 不确定是否适用于 mysql,但可能需要将别名包装在刻度 `daysdiff` 中。

标签: sql sql-server tsql sql-server-2005


【解决方案1】:
SELECT
   logcount, logUserID, maxlogtm,
   DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
WHERE ( DATEDIFF(day, maxlogtm, GETDATE() > 120)

通常您不能在WHERE 子句中引用字段别名。 (把它想象成整个 SELECT 包括别名,都应用在 WHERE 子句之后。)

但是,正如其他答案中提到的,您可以强制 SQL 在 WHERE 子句之前处理 SELECT 。这通常使用括号来强制操作的逻辑顺序或使用公用表表达式 (CTE):

括号/子选择:

SELECT
   *
FROM
(
   SELECT
      logcount, logUserID, maxlogtm,
      DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
   FROM statslogsummary   
) as innerTable
WHERE daysdiff > 120

或者查看 Adam 的 CTE 版本的答案。

【讨论】:

  • 这是不可能的,因为按时间顺序,WHERE 发生在 SELECT 之前,它始终是执行链中的最后一步。参考 - stackoverflow.com/questions/356675/…
  • afaik 如果选择中的别名是相关子查询,这将起作用,而 CTE 解决方案不会。
  • 正如 Pascal 在他的回答 stackoverflow.com/a/38822328/282887 中提到的,您可以使用 HAVING 子句,它似乎比子查询工作得更快。
  • @Bakhtiyor HAVING 答案在大多数 SQL 环境中都不起作用,包括这个问题所涉及的 MS-SQL。 (在 T-SQL 中,HAVING 需要聚合函数。)
  • 直到我刚刚遇到这个问题,我才知道你不能引用别名。喜欢这种解决方法...这对性能有什么重大影响吗?
【解决方案2】:

如果您想在WHERE 子句中使用别名,则需要将其包装在子选择中,或者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 是否有额外的开销?
  • CTE 只是子查询的更漂亮的语法,因此性能与此类似。根据我的经验,性能差异并没有让我担心这样的操作,但是在你的环境中测试它应该相当简单,看看你的特定表/查询是否受到了不利影响。公式专门在 where 子句中。我怀疑你不会注意到有什么不同。
  • CTE 非常好,直到您尝试将其用作子查询。我不得不求助于将它们创建为嵌套它们的视图。我认为这是一个严重的 SQL 缺陷
【解决方案3】:

不重复代码的最有效方法是使用 HAVING 而不是 WHERE

SELECT logcount, logUserID, maxlogtm
   , DATEDIFF(day, maxlogtm, GETDATE()) AS daysdiff
FROM statslogsummary
HAVING daysdiff > 120

【讨论】:

  • 我认为在别名上使用 HAVING 不是标准的(不过它确实适用于 MySQL)。具体来说,我认为它不适用于 SQL Server。
  • SQL Server:[S0001][207] Invalid column name 'daysdiff'
  • SQL Server:[S0001][8121] Column 'day' is invalid in the HAVING clause because it is not contained in either an aggregate function or the GROUP BY clause.
【解决方案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 关键字不能 与聚合函数一起使用。

      【讨论】:

      • 问题是关于sql-server的
      • 尽管问题是关于 SQL Server 的,但这个答案对我们使用 mysql 的人非常有帮助,他们是通过谷歌来到这里的!谷歌没有索引问题标签,所以感谢这个答案!
      【解决方案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/outerquery 包装整个查询
      • 可以参考WHERE/GROUP BY/ORDER BY
      • 可能有更好的性能(单次执行)

      【讨论】:

      • 值得一提的是它只适用于 SQL Server
      • @MartinZinovsky 问题标记为sql-servert-sql :)
      【解决方案8】:

      来到这里看起来与此类似,但使用 CASE WHEN,并以这样的方式结束:WHERE (CASE WHEN COLUMN1=COLUMN2 THEN '1' ELSE '0' END) = 0 也许您可以直接在WHERE 中使用DATEDIFF。 类似的东西:

      SELECT logcount, logUserID, maxlogtm
      FROM statslogsummary
      WHERE (DATEDIFF(day, maxlogtm, GETDATE())) > 120
      

      【讨论】:

        【解决方案9】:

        对我来说,在 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
        

        干杯, 凯尔

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-15
          • 2020-05-14
          相关资源
          最近更新 更多