【问题标题】:Find the Count of Consecutive Occurrence in Table using SQL使用 SQL 查找表中连续出现的计数
【发布时间】:2021-11-10 22:12:07
【问题描述】:

在此处输入代码在我的 SQl 服务器中有一个这样的表

  NTN        |   Channel          Date_Time
006175A      |   Yellow         15-9-2021 10:16:00:00
0061751      |   Green          15-9-2021 10:15:00:00
00617523     |   Red            15-9-2021 10:14:00:00
006175A      |   Green          15-9-2021 10:13:00:00
006175A      |   Green          15-9-2021 10:12:00:00
006175A      |   Green          15-9-2021 10:11:00:00
0061756      |   Red            15-9-2021 10:10:00:00
00617523     |   Green          16-9-2021 10:10:00:00
00617523     |   Green          16-9-2021 10:12:00:00

现在我要做的是为我的 NTN 列显示连续的绿色,如下所示:

 NTN        |    Greens |  Max(Date_Time)          |   Min(Date_Time)
 006175A    |     3     |  15-9-2021 10:13:00:000  |   15-9-2021 10:11:00:00
 00617523   |     2     |  16-9-2021 10:12:00:000  |   16-9-2021 10:10:00:00 

谁能帮助我如何使用 SQL Server 实现这一目标

【问题讨论】:

  • 为什么 NTN=0061751 没有出现在您的预期结果中,最长序列为 1?
  • 我没有时间写一个完整的答案,但是在谷歌上搜索的对你有帮助的关键词是“差距和岛屿”。
  • 为什么你的日期时间会在几分钟内减少,但在几天内就会增加?
  • 如果连续三个绿色,如果中间出现红色,但对于不同的 NTN,这会改变预期结果吗?
  • @MatBailie 是的,它会改变预期结果,因为我想要相同 NTN 的连续果岭。

标签: sql tsql sql-server-2016 aggregation gaps-and-islands


【解决方案1】:

嗯。 . .最后的果岭满足这个条件:在该行之后和最后一个果岭之前没有非果岭。您可以使用窗口函数来做到这一点:

select ntn, count(*) as last_greens, min(date_time), max(date_Time)
from (select t.*,
             sum(case when channel <> 'Green' then 1 else 0 end) over (partition by ntn order by date_time desc) as non_greens_after
      from (select t.*,
                   max(case when channel = 'Green' then date_time end) over (partition by ntn order by date_time) as max_green_dt
            from t
           ) t
      where date_time <= max_green_dt
     ) t
where non_greens_after = 0 and channel = 'Green'
group by ntn;

Here 是一个 dbfiddle。

注意:您没有解释为什么不包括 '0061751'。如果您想要至少两个果岭,请添加 having count(*) &gt;= 2

【讨论】:

  • 我的实际数据中最后一个绿色行后面有一个非绿色。
  • 不确定我是否做错了,但如果表名为“t”,则在运行代码时出现以下错误:选择列表中的列 't.NTN' 无效,因为它不包含在聚合函数或 GROUP BY 子句中。
【解决方案2】:
WITH
  sorted AS
(
  SELECT
    *,
    ROW_NUMBER() OVER (    ORDER BY date_time
                      )
                        AS seq_id,
    ROW_NUMBER() OVER (PARTITION BY ntn, channel
                           ORDER BY date_time
                      )
                        AS ntn_channel_seq_id
  FROM
    your_table
)
SELECT
  ntn,
  COUNT(*),
  MIN(date_time),
  MAX(date_time)
FROM
  sorted
WHERE
  channel = 'Green'
GROUP BY
  ntn,
  seq_id - ntn_channel_seq_id
HAVING
  COUNT(*) > 1
ORDER BY
  ntn,
  seq_id - ntn_channel_seq_id

带有一系列略有不同的测试集的演示:

【讨论】:

  • 你在“两个序列之间的差异”问题上击败了我。我正忙着为 OP 添加其他东西。干得好!
【解决方案3】:

@humair-hassan,

首先,通过以代码的形式发布“Readily Consumable Data”来帮助其他人在未来帮助您,让他人可以运行该代码来创建并使用您的测试数据填充表格。您将更快地获得更多更好的答案。

这是对您发布的测试数据执行此操作的一种方法。请注意,通常最好以临时表的形式执行此操作,以便数据保持不变,这样更容易编写测试代码。

--===== Set the date format to match the format of the given test data.
    SET DATEFORMAT DMY
;
--===== Create the data as a readily consumable table.
   DROP TABLE IF EXISTS #TestTable;
 SELECT  NTN       = CONVERT(VARCHAR(10),v.NTN)
        ,Channel   = CONVERT(VARCHAR(10),v.Channel)
        ,Date_Time = CONVERT(DATETIME   ,v.Date_Time)
   INTO #TestTable
   FROM (VALUES
         ('006175A' ,'Yellow','15-9-2021 10:16:00:00')
        ,('0061751' ,'Green' ,'15-9-2021 10:15:00:00')
        ,('00617523','Red'   ,'15-9-2021 10:14:00:00')
        ,('006175A' ,'Green' ,'15-9-2021 10:13:00:00')
        ,('006175A' ,'Green' ,'15-9-2021 10:12:00:00')
        ,('006175A' ,'Green' ,'15-9-2021 10:11:00:00')
        ,('0061756' ,'Red'   ,'15-9-2021 10:10:00:00')
        ,('00617523','Green' ,'16-9-2021 10:10:00:00')
        ,('00617523','Green' ,'16-9-2021 10:12:00:00')
        )v(NTN,Channel,Date_Time)
;

[编辑] @MatBailie 指出了我的代码中的一个缺陷,我已将其删除,因此没有人会在使用它时出错。

我还检查了他提交的代码,他的代码是正确的。

我留下了测试数据创建脚本,以防其他人想尝试一下。

【讨论】:

  • 这会将所有出现的 Green 放在同一个组中,对于每个 ntn(它不应该)。 OP 只需要连续出现 Green 和相同的 ntn,即使来自其他 ntns 等的值也会考虑“中断”。请参阅我的代码,并比较结果; dbfiddle.uk/…
  • 谢谢。你是对的。我已经删除了我的错误代码,这样没有人会误用它。
猜你喜欢
  • 2021-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-23
  • 2015-07-09
  • 2021-02-20
  • 1970-01-01
  • 2018-04-18
相关资源
最近更新 更多