SQL选择动态日期范围之间的行

时间:2019-01-10 16:38:55

标签: sql sql-server

对于每个NAME,我要查询CALL_DATE的数据,该数据小于或等于START_DATE起的三个月。以下是我的尝试,但出现错误。

查询:

SELECT CALLER_NAME AS "NAME", 
       CAST(CREATED AS DATE) AS "CALL_DATE", 
       DURATION, 
       CAST(START_DATE AS DATE) AS "START_DATE"
FROM table1 
GROUP BY NAME
    HAVING CAST(CREATED AS DATE) >= MIN(CAST(START_DATE AS DATE)) AND CAST(CREATED AS DATE) <= DATEADD(MONTH, 3, CAST(START_DATE AS DATE))
ORDER BY AE_NAME, CALL_DATE

错误

  

信息8121,第16级,状态1,第12行   在HAVING子句中,“ CREATED”列无效,因为它不在聚合函数或GROUP BY子句中。

     

信息8121,级别16,状态1,第12行在以下位置无效:“ START_DATE”列   HAVING子句,因为它既不包含在任何聚合中   函数或GROUP BY子句。

我了解为什么会收到此错误,但我不知道如何解决。非常感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

您需要按原始字段名称(而不是别名)进行分组。您还需要对所有未聚合的内容进行分组。

这应该有效:

SELECT CALLER_NAME AS "NAME", 
       CAST(CREATED AS DATE) AS "CALL_DATE", 
       DURATION, 
       CAST(START_DATE AS DATE) AS "START_DATE"
FROM table1 
GROUP BY  CALLER_NAME, CREATED, DURATION, START_DATE
    HAVING CAST(CREATED AS DATE) >= MIN(CAST(START_DATE AS DATE)) AND CAST(CREATED AS DATE) <= DATEADD(MONTH, 3, CAST(START_DATE AS DATE))
ORDER BY AE_NAME, CALL_DATE

答案 1 :(得分:1)

在“分组依据”子句中添加“创建”和“ START_DATE”。

SELECT CALLER_NAME AS "NAME", 
       CAST(CREATED AS DATE) AS "CALL_DATE", 
       DURATION, 
       CAST(START_DATE AS DATE) AS "START_DATE"
FROM table1 
GROUP BY NAME, CREATED, START_DATE
    HAVING CAST(CREATED AS DATE) >= MIN(CAST(START_DATE AS DATE)) AND CAST(CREATED AS DATE) <= DATEADD(MONTH, 3, CAST(START_DATE AS DATE))
ORDER BY AE_NAME, CALL_DATE

或者使用WHERE而不是HAVING

SELECT CALLER_NAME AS "NAME", 
       CAST(CREATED AS DATE) AS "CALL_DATE", 
       DURATION, 
       CAST(START_DATE AS DATE) AS "START_DATE"
FROM table1 
GROUP BY NAME
    WHER CAST(CREATED AS DATE) >= MIN(CAST(START_DATE AS DATE)) AND CAST(CREATED AS DATE) <= DATEADD(MONTH, 3, CAST(START_DATE AS DATE))
ORDER BY AE_NAME, CALL_DATE

答案 2 :(得分:0)

恐怕您必须通过从头开始重写来修复它。如错误所示,当您在一个或多个列上进行GROUP时,真正真正可以进行选择的唯一内容是GROUP BY子句中的那些列(或表达式),或者是聚合函数,在这种情况下,这些函数适用于ALL具有给定名称的行。

同时选择NAME和(例如)DURATION时,它不认为您想要与一个NAME位于同一行的DURATION值,而是所有功能中的某些函数(求和,最小值,最大值等) NAME旁边的DURATION。您不会在选择其他任何列的情况下执行此操作,无论是两个日期还是持续时间。

这很令人困惑,我在猜测您要做什么,这实际上不是每个NAME多行汇总报告。我认为,您希望每行具有NAME的行都输出,但是只需选择以下行:

1)CREATED是> =整个表中的最小START_DATE 2)创建时间是该行中START_DATE之后的三个月之内

唯一需要的汇总就是找到最小的START_DATE。最容易读取的代码是子查询。如果我猜对了,那么该代码将是(不确定您的SQL变体,我将尝试在CAST语法中使用cut&paste):

SELECT CALLER_NAME AS "NAME", 
       CAST(CREATED AS DATE) AS "CALL_DATE", 
       DURATION, 
       CAST(START_DATE AS DATE) AS "START_DATE"
FROM table1 
WHERE CAST(CREATED AS DATE) >= (SELECT MIN(CAST(START_DATE AS DATE)) FROM table1)
  AND CAST(CREATED AS DATE) <= DATEADD(MONTH, 3, CAST(START_DATE AS DATE));