SQL:检测具有相同键的连续行的连续块

如何解决SQL:检测具有相同键的连续行的连续块

我的问题归结为以下几点。我有一个带有一些自然排序的表,其中我有一个可能会随着时间重复的键值。我想找到键相同的块,然后更改,然后恢复相同。示例:

  1. A
  2. A
  3. B
  4. B
  5. B
  6. C
  7. C
  8. A
  9. A
  10. C
  11. C

这里是我想要的结果

  1. A,1-2
  2. B,3-5
  3. C,6-7
  4. A,8-9
  5. C,10-11

所以我不能使用那个键值 A、B、C 来分组,因为同一个键可以出现多次,我只想挤出不间断的重复出现。

不用说,我想要一个可以想出的最简单的 sql。它将使用 OLAP 窗口函数

我通常很擅长复杂的 sql,但对于序列我不太擅长。当然,我会自己做一些工作,并在随后的编辑中在这个问题下面附上一些想法。

让我们首先定义我们讨论的表格:

CREATE TABLE Seq (
  num integer,key char
);

更新 1:做一些研究我在这里发现了一个类似的问题:How to find consecutive rows based on the value of a column? 但问题和答案都包含在很多额外的东西中并且令人困惑。

更新 2:我已经得到了一个答案,谢谢。现在正在检查。这是我的测试,即使我们说话,我也正在输入 Postgresql

CREATE TABLE Seq ( num int,key char );
INSERT INTO Seq VALUES 
   (1,'A'),(2,'B'),(3,(5,(6,'C'),(7,(8,(9,(10,(11,'C');

更新 3:解决方案的第一个竞争者是这个

SELECT key,min(num),max(num)
  FROM (
    SELECT seq.*,row_number() over (partition by key order by num) as seqnum
      FROM Seq 
  ) s
  GROUP BY key,(num - seqnum) 
  ORDER BY min;

产量:

 key | min | max
-----+-----+-----
 A   |   1 |   2
 B   |   2 |   3
 B   |   5 |   5
 C   |   6 |   7
 A   |   8 |   9
 C   |  10 |  11
(6 rows)

出于某种原因,B 重复了两次,我明白为什么,我在测试数据中犯了一个错误”,跳过序列 num 4 并直接从 3 到 5。

这个错误是幸运的,因为它允许我指出,虽然在这个例子中序列号是离散的,但我希望序列来自某个连续域(例如时间)。

我犯了另一个错误”,因为我重复了 num 2。这是允许的吗?可能不是。所以清理示例,删除重复但留下空白:

DROP TABLE Seq;
CREATE TABLE Seq ( num int,(4,(12,'C');

这仍然给我们留下了重复的 B 块:

 key | min | max
-----+-----+-----
 A   |   1 |   2
 B   |   3 |   4
 B   |   6 |   6
 C   |   7 |   8
 A   |   9 |  10
 C   |  11 |  12
(6 rows)

现在根据 Gordon Linoff 的第一个直觉来尝试理解它并添加进去:

SELECT s.*,num - seqnum AS diff 
  FROM (
    SELECT seq.*,row_number() over (partition by key order by num) as seqnum
      FROM Seq
    ) s
  ORDER BY num;

这是分组前的 num - seqnum 技巧:

 num | key | seqnum | diff
-----+-----+--------+------
   1 | A   |      1 |    0
   2 | A   |      2 |    0
   3 | B   |      1 |    2
   4 | B   |      2 |    2
   6 | B   |      3 |    3
   7 | C   |      1 |    6
   8 | C   |      2 |    6
   9 | A   |      3 |    6
  10 | A   |      4 |    6
  11 | C   |      3 |    8
  12 | C   |      4 |    8
(11 rows)

我怀疑这是否是答案。

解决方法

这回答了原来的问题。

您可以枚举每个键的行并从 num 中减去它。瞧!当相邻行上的 key 为常量时,此数字为常量:

select key,min(num),max(num)
from (select seq.*,row_number() over (partition by key order by num) as seqnum
      from seq
     ) s
group by key,(num - seqnum);

Here 是一个 dbfiddle,表明它有效。

,

由于存在间隙,您不能像 Gordon 的解决方案建议的那样直接使用 numRow_number也是。

select key,row_number() over (order by  num) as rn,(rn - seqnum)
order by min(num);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?