I have two tables:
Table 1 consists of ID and INDX. INDX is the date around the CODE from Table2 needs to be verified.
Table2 consists of ID, CODE, DAT, QRTR. DAT is the date on which the CODE is given with corresponding quarter of the year in QRTR.

表1:

ID INDX
1 2014-06-07

表2:

ID CODE DAT QRTR
1 A 2013-08-20 20133
1 A 2013-12-20 20134
1 A 2014-01-02 20141
1 A 2014-11-18 20144
1 A 2015-02-08 20151
1 A 2015-04-20 20152
1 A 2015-11-16 20154
1 A 2016-04-12 20162
1 A 2017-01-20 20171
1 A 2017-12-12 20174
1 A 2018-01-03 20181
1 A 2019-05-20 20193
1 A 2020-01-01 20201
1 A 2021-04-16 20212
1 A 2021-08-20 20213
1 A 2021-12-30 20214

Now I need to know if CODE 'A' was present within 300 days until INDX date.
If so, I need to verify if CODE 'A' is given at least one QRTR per year starting with the first data entry of CODE 'A' (within 300 days prior INDX) including the future CODEs.

我try 了以下几种方法:

SELECT
    t1.ID,
    years.Year,
    CASE
        WHEN EXISTS (
            SELECT 1
            FROM table2 t2
            WHERE t2.ID = t1.ID
                AND t2.CODE = 'A'
                AND years.Year = YEAR(DATEADD(QUARTER, t2.QRTR % 10 - 1, DATEADD(YEAR, t2.QRTR / 10 - 1900, '19000101')))
        ) THEN 'Yes'
        ELSE 'No'
    END AS IsQuarterly
FROM
    (
        SELECT DISTINCT ID
        FROM table1
    ) AS t1
CROSS JOIN
    (
        SELECT DISTINCT YEAR(DATEADD(QUARTER, (QRTR % 10) - 1, DATEADD(YEAR, (QRTR / 10) - 1900, '19000101'))) AS Year
        FROM table2
        WHERE CODE = 'A'
    ) AS years
ORDER BY
    t1.ID,
    years.Year;

日期:db<>fiddle.(用谷歌翻译翻译)

为了表达清晰起见,我在上面的表格中只包含了ID 1.

通过我的查询,我只得到每年是否至少有一个CODE‘A’存在,但直到CODE‘A’出现在哪个时间,以及是否已经有一个CODE‘A’的新时期,我才能得到信息.

我预计会出现以下情况,因为我认为最好是得出一个CODE个‘A’每年至少出现一个QRTR个‘A’的时期.

ID START END
1 2013-08-20 2021-12-30
2 2017-12-12 2019-05-20
2 2021-08-20 2021-12-30

我不确定显示结果的最佳解决方案是什么.

推荐答案

This is a classic Gaps-and-Islands problem.

您首先需要每年汇总数据,然后判断每年的总计数.

然后使用间隔和孤岛技术将其分成连续年份的几组行,最后获取每一组的最小日期和最大日期.

在较早版本的SQL Server中,使用YEAR(而不是DATETRUNC(year,,如果可用,后者的性能会更好.

WITH Data AS (
    SELECT
      t2.ID,
      Year = DATETRUNC(year, t2.DAT),
      MinDate = MIN(t2.DAT),
      Maxdate = MAX(t2.DAT),
      PrevYear =   LAG(DATETRUNC(year, t2.DAT)) OVER (PARTITION BY t2.ID ORDER BY DATETRUNC(year, t2.DAT)),
      NextYear =  LEAD(DATETRUNC(year, t2.DAT)) OVER (PARTITION BY t2.ID ORDER BY DATETRUNC(year, t2.DAT))
    FROM Table1 t1
    JOIN Table2 t2
      ON t2.ID = t1.ID
     AND t2.DAT >= DATEADD(day, -300, t1.INDX)
    GROUP BY
      t2.ID,
      DATETRUNC(year, t2.DAT)
),
Islands AS (
    SELECT
      *,
      NextMaxDate = LEAD(d.MaxDate) OVER (PARTITION BY d.ID ORDER BY d.Year)
    FROM Data d
    WHERE d.PrevYear IS NULL
       OR d.PrevYear < DATEADD(year, -1, Year)
       OR d.NextYear IS NULL
       OR d.NextYear > DATEADD(year, 1, Year)
)
SELECT
  ID,
  Start = MinDate,
  [End] = ISNULL(NextMaxDate, MaxDate)
FROM Islands i
WHERE i.PrevYear IS NULL
   OR i.PrevYear < DATEADD(year, -1, Year);

db<>fiddle

Sql相关问答推荐

查询多个表并返回合并在联合列上的所有表中的所有行

LAG函数通过丢弃空值返回前一行

如何用QuestDB生成蜡烛图?

根据时间、状态和相关行在PostgreSQL中的存在来删除行

TSQL如何为群分配号码

组合2个分区表的postgres视图的执行计划正在访问所有分区

显示十进制列,但尽可能显示为整数

PostgreSQL中递归CTE查询的故障过滤

如何修复初学者 SQL INNER JOIN 查询错误

Postgresql 生成器列导致语法错误

SQL SUM Filter逻辑解释

我可以在 T-SQL (SQL Server) 的函数内使用 OPTION 子句吗?

将空 JSON 数组添加到 SQL Server 表列中的 JSON 字符串

Postgres更新增量之间的差异

如何在 SQL Server 中将 -13422.8450 舍入到 -13422.84

以 15 分钟为间隔的使用情况SQL 查询

基于源表的 SQL INSERT、UPDATE 和 DELETE

连续几天购买的客户

SQL - 使用子查询返回多行的 LIKE 命令

将单行中的多个行值转换为列