为什么我不能在 WHERE 子句中使用我的列别名?

问题描述

我想将当前行的值与前一行的值进行比较。我想出了这个,但它不起作用。它找不到 PREV_NUMBER_OF_PEOPLE 所以我的 WHERE 子句无效。我不允许使用 WITH。有人有想法吗?

SELECT
   ID,NUMBER_OF_PEOPLE,LAG(NUMBER_OF_PEOPLE) OVER (ORDER BY DATE) AS PREV_NUMBER_OF_PEOPLE,DATE 
FROM (
   SELECT * FROM DATAFRAME
   WHERE DATE>=CURRENT_DATE-90
   ORDER BY DATE DESC
) AS InnerQuery
WHERE NUMBER_OF_PEOPLE <> PREV_NUMBER_OF_PEOPLE 

解决方法

您可以使用公用表表达式 (CTE) 来拆分查询处理。

像这样:

WITH cte1 AS
(
  SELECT * -- field list is advised...
  FROM DATAFRAME
  WHERE DATE >= CURRENT_DATE-90
),cte2 AS
(
  SELECT ID,NUMBER_OF_PEOPLE,LAG(NUMBER_OF_PEOPLE) OVER (ORDER BY DATE) AS PREV_NUMBER_OF_PEOPLE,DATE 
  FROM cte1
)
SELECT ID,PREV_NUMBER_OF_PEOPLE,DATE 
FROM cte2
WHERE NUMBER_OF_PEOPLE <> PREV_NUMBER_OF_PEOPLE
ORDER BY DATE DESC;
,

逻辑查询处理是定义正确结果的查询的概念解释,与查询子句的键入顺序不同,它从评估 FROM 子句开始。理解逻辑查询处理对于正确理解 T-SQL 至关重要。

在 T-SQL 中用于检索数据的主要语句是 SELECT 语句。以下是按您应该键入的顺序(称为“键入顺序”)指定的主要查询子句:

  • 选择
  • 来自
  • 哪里
  • 分组依据
  • 拥有
  • 订购者

但如前所述,逻辑查询处理顺序,即概念解释顺序,是不同的。它以 FROM 子句开头。下面是六个主要查询子句的逻辑查询处理顺序:

  • 来自
  • 哪里
  • 分组依据
  • 拥有
  • 选择
  • 订购者

您可以使用 CTE :

  WITH CTE1 AS (
SELECT * FROM DATAFRAME
       WHERE DATE>=CURRENT_DATE-90
       
),CTE2 AS (
SELECT
       ID,DATE 
    FROM CT2
)

SELECT * FROM CT2
WHERE NUMBER_OF_PEOPLE <> PREV_NUMBER_OF_PEOPLE
,

只需将 lag() 移动到派生表中即可。

SELECT *
FROM (
   SELECT id,number_of_people,lag(number_of_people) over (order by date) as prev_number_of_people,date
   FROM dataframe
   WHERE date >= current_date - 90
) AS InnerQuery
WHERE number_of_people <> prev_number_of_people 
ORDER BY date DESC
,

您的查询有几个问题:

  • 过滤条件应该在外部查询中。
  • 新的列定义应该在内部查询中。
  • order by 应该在外部查询中。

通过这些更改,它应该可以正常工作:

SELECT ID,DATE
FROM (SELECT D.*,LAG(NUMBER_OF_PEOPLE) OVER (ORDER BY DATE) AS PREV_NUMBER_OF_PEOPLE
      FROM DATAFRAME D
     ) AS InnerQuery
WHERE NUMBER_OF_PEOPLE <> PREV_NUMBER_OF_PEOPLE AND
      DATE >= CURRENT_DATE - 90
ORDER BY DATE DESC;

您需要在 LAG() 之后进行过滤,以便您可以在日期范围内包含最早的一天。如果您在内部查询中进行过滤,则在这种情况下 LAG() 将返回 NULL

您需要在子查询中定义别名,以便您可以在 WHERE 中引用它。 SELECT 中定义的别名不能用于相应的 WHERE。这是一条 SQL 规则,与您使用的数据库无关。