如何使用 SQL 识别记录中的记录模式序列?
How do you identify record pattern sequences in records using TSQL?
这对我来说是一个相当新的练习,但我需要找到一种方法来识别 table 中的模式序列。
因此,例如,假设我有一个类似于以下内容的简单 table:
现在我想做的是识别并分组所有具有值 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, ROW_NUMBER() OVER(ORDER BY k) AS rn
FROM (VALUES(1, 5), (2, 9), (3, 6)) x(k,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 k) AS rn
FROM (VALUES(1, 5), (2, 9), (3, 6)) x(k,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 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
注意: 这个答案的初始版本使用了 INNER JOIN
到 Seq
。如果 table 包含像 5, 42, 9, 6
这样的值,这将不起作用,因为 42
将被 INNER JOIN
过滤掉并且该序列被错误地识别为有效序列。此编辑归功于@HABO。
不是很优化,但我认为正确的答案:
CREATE TABLE pattern (
rowID INT IDENTITY(1,1) PRIMARY KEY,
rowValue INT NOT NULL
);
INSERT INTO pattern (rowValue) VALUES (5);
INSERT INTO pattern (rowValue) VALUES (9);
INSERT INTO pattern (rowValue) VALUES (6);
SELECT * FROM pattern;
SELECT Trg.* FROM Keys Trg
INNER JOIN pattern Pt ON (Trg.fValue = Pt.rowValue)
INNER JOIN (
SELECT K.fKey - P.rowID AS X, COUNT(*) AS Xc FROM Keys K
LEFT JOIN pattern P ON (K.fValue = P.rowValue)
WHERE
(P.rowID IS NOT NULL)
GROUP BY K.fKey - P.rowID
HAVING COUNT(*) = (SELECT COUNT(*) FROM pattern)
) Z ON (Trg.fKey - Pt.rowID = Z.X);
我使用 table 作为模式将其连接到主 table。我计算 Key
和模式 Key
之间的差异,我只显示差异匹配的行(并且行计数模式 table 内的差异匹配行)。
这对我来说是一个相当新的练习,但我需要找到一种方法来识别 table 中的模式序列。 因此,例如,假设我有一个类似于以下内容的简单 table:
现在我想做的是识别并分组所有具有值 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, ROW_NUMBER() OVER(ORDER BY k) AS rn
FROM (VALUES(1, 5), (2, 9), (3, 6)) x(k,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 k) AS rn
FROM (VALUES(1, 5), (2, 9), (3, 6)) x(k,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 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
注意: 这个答案的初始版本使用了 INNER JOIN
到 Seq
。如果 table 包含像 5, 42, 9, 6
这样的值,这将不起作用,因为 42
将被 INNER JOIN
过滤掉并且该序列被错误地识别为有效序列。此编辑归功于@HABO。
不是很优化,但我认为正确的答案:
CREATE TABLE pattern (
rowID INT IDENTITY(1,1) PRIMARY KEY,
rowValue INT NOT NULL
);
INSERT INTO pattern (rowValue) VALUES (5);
INSERT INTO pattern (rowValue) VALUES (9);
INSERT INTO pattern (rowValue) VALUES (6);
SELECT * FROM pattern;
SELECT Trg.* FROM Keys Trg
INNER JOIN pattern Pt ON (Trg.fValue = Pt.rowValue)
INNER JOIN (
SELECT K.fKey - P.rowID AS X, COUNT(*) AS Xc FROM Keys K
LEFT JOIN pattern P ON (K.fValue = P.rowValue)
WHERE
(P.rowID IS NOT NULL)
GROUP BY K.fKey - P.rowID
HAVING COUNT(*) = (SELECT COUNT(*) FROM pattern)
) Z ON (Trg.fKey - Pt.rowID = Z.X);
我使用 table 作为模式将其连接到主 table。我计算 Key
和模式 Key
之间的差异,我只显示差异匹配的行(并且行计数模式 table 内的差异匹配行)。