sql-server – 如何使用TSQL识别记录中的记录模式序列?

这对我来说是一个相当新的练习,但我需要找到一种方法来识别表格中的模式序列.
例如,假设我有一个类似于以下内容的简单表:

现在我想要做的是识别和分组所有具有值为5,9和6的序列模式的记录,并在查询显示它们.你会如何使用T-sql完成这项任务?

结果应如下所示:

我已经找到了一些可能实现这一目标的潜在例子,却找不到真正有用的东西.

解决方法

您可以使用包含在CTE中的以下查询,以便将序列号分配给序列中包含的值:
;WITH Seq AS (
    SELECT v,ROW_NUMBER() OVER(ORDER BY k) AS rn
    FROM (VALUES(1,5),(2,9),(3,6)) x(k,v)
)

输出

v   rn
-------
5   1
9   2
6   3

使用上面的CTE,您可以识别孤岛,即包含整个序列的连续行的切片:

;WITH Seq AS (
    SELECT v,v)
),Grp AS (
SELECT [Key],[Value],ROW_NUMBER() OVER (ORDER BY [Key]) - rn AS grp            
FROM mytable AS m
LEFT JOIN Seq AS s ON m.Value = s.v
)
SELECT *
FROM Grp

输出

Key Value   grp
   -----------------
    1   5       0
    2   9       0
    3   6       0
    6   5       3
    7   9       3
    8   6       3

grp字段可帮助您准确识别这些岛屿.

您现在需要做的就是过滤掉部分组:

;WITH Seq AS (
    SELECT v,ROW_NUMBER() OVER (ORDER BY [Key]) - rn AS grp            
FROM mytable AS m
LEFT JOIN Seq AS s ON m.Value = s.v
)
SELECT g1.[Key],g1.[Value]
FROM Grp AS g1
INNER JOIN (
   SELECT grp
   FROM Grp
   GROUP BY grp
   HAVING COUNT(*) = 3 ) AS g2
ON g1.grp = g2.grp

Demo here

注意:此答案的初始版本使用INNER JOIN到Seq.如果表包含5,42,9,6等值,则这将无效,因为42将被INNER JOIN过滤掉,并且此序列被错误地识别为有效序列.感谢@HABO进行此编辑.

相关文章

(一)日志传送架构 (1.1)相关服务器 主服务器 :用于生产的服务器,上面运行这生产SQL Server数据库...
(一)事故背景 最近在SQL Server 2012生产数据库上配置完事物复制(发布订阅)后,生产数据库业务出现了...
(一)测试目的 目前公司使用的SQL SERVER 2012高可用环境为主备模式,其中主库可执行读写操作,备库既...
(一)背景个人在使用sql server时,用到了sql server的发布订阅来做主从同步,类似MySQL的异步复制。在...
UNION和OR谓词 找出 product 和 product2 中售价高于 500 的商品的基本信息. select * from product wh...
datawhale组队学习task03