【问题标题】:SQL Occurrence of Sequence Number序列号的SQL出现
【发布时间】:2020-02-21 18:15:17
【问题描述】:

我想查找是否有任何 Name 仅在连续序列中连续出现 4 次或更多 SeqNo。 如果 seqNo 有中断但 4 行或更多行是连续的,那么我也需要该名称。

例子:

SeqNo    Name
10     | A
15     | A
16     | A
17     | A
18     | A
9      | B
10     | B
13     | B
14     | B
6      | C
7      | C
9      | C
10     | C
OUTPUT:
A

以下是任何帮助的脚本。

create table testseq (Id int, Name char)

INSERT into testseq values
(10, 'A'),
(15, 'A'),
(16, 'A'),
(17, 'A'),
(18, 'A'),
(9, 'B'),
(10, 'B'),
(13, 'B'),
(14, 'B'),
(6, 'C'),
(7, 'C'),
(9, 'C'),
(10, 'C')

SELECT * FROM testseq

【问题讨论】:

  • A 序列中只有 3 个连续的 seqno,但您想要 4 个。您确定您的样本数据/预期结果吗?
  • 你想要seqnos 增加 1,还是只是增加,不管增加多少?

标签: sql group-by row-number gaps-and-islands


【解决方案1】:

您可以为此使用一些间隙和孤岛技术。

如果您希望 names 至少有 4 条连续记录,其中 seqno 增加 1,那么您可以使用 seqno androw_number() 之间的差异来定义组,然后聚合:

select distinct name
from (
    select t.*, row_number() over(partition by name order by seqno) rn
    from testseq t
) t
group by name, rn - seqno
having count(*) >= 4

请注意,对于您的示例数据,这不会返回任何行。 A 有 3 条连续记录,其中 seqno 递增 1BC 有两条。

【讨论】:

    【解决方案2】:

    我并不认为这是一个“差距和孤岛”问题。您只是在寻找最少数量的相邻行。这很容易使用lag()lead() 处理:

    select t.*
    from (select t.*,
                 lead(seqno, 3) over (partition by name order by seqno) as seqno_name_3
          from t
         ) t
    where seqno_name_3 = seqno + 3;
    

    这会检查同名的第三个序列号。第三个之后表示四个名字连续相同。

    如果您只想要名称并处理重复项:

    select distinct name
    from (select t.*,
                 lead(seqno, 3) over (partition by name order by seqno) as seqno_name_3
          from t
         ) t
    where seqno_name_3 = seqno + 3;
    

    如果序列号可以有间隔(但在其他方面相邻):

    select distinct name
    from (select t.*,
                 lead(seqno, 3) over (partition by name order by seqno) as seqno_name_3,
                 lead(seqno, 3) over (order by seqno) as seqno_3
          from t
         ) t
    where seqno_name_3 = seqno_3;
    

    【讨论】:

      【解决方案3】:

      普通 SQL 中的解决方案,没有LAG()LEAD()ROW_NUMBER()

      SELECT t1.Name
      FROM testseq t1
      WHERE (
          SELECT count(t2.Id)
          FROM testseq t2
          WHERE t2.Name=t1.Name
                and t2.Id between t1.Id and t1.Id+3
              GROUP BY t2.Name)>=4
      GROUP BY t1.Name;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-13
        • 2016-03-12
        • 1970-01-01
        相关资源
        最近更新 更多