如何识别 SQL 中的模式
How to identify pattern in SQL
这是我的table。它确实由 A、B 和 C 列组成。一次只有一列值为真。
我的任务是根据最近的五行来识别模式。
例如
我需要搜索整个 table 以查找这五个值何时重复。
如果重复,这些模式的下一个可用值是多少,并显示在该模式之后找到 A、B 和 C 值的次数。
如何在 SQL 中完成此操作?我正在使用甲骨文 11g。谢谢
您可以将 a, b, c
值转换为一个三进制数,然后计算该行和前 4 行的值,就好像这些行的三进制值包含一个 5 位数的三进制数,然后使用解析查找下一次出现并计算出现次数的函数:
SELECT id,
a,
b,
c,
CASE
WHEN grp_value IS NULL
THEN NULL
ELSE MIN(id) OVER (
PARTITION BY grp_value
ORDER BY id
ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING
) + 1
END AS row_after_next_match,
CASE
WHEN grp_value IS NULL
THEN 0
ELSE COUNT(id) OVER ( PARTITION BY grp_value )
END AS num_matches
FROM (
SELECT id,
a,
b,
c,
value,
81 * LAG(value,4) OVER ( ORDER BY id ) +
27 * LAG(value,3) OVER ( ORDER BY id ) +
9 * LAG(value,2) OVER ( ORDER BY id ) +
3 * LAG(value,1) OVER ( ORDER BY id ) +
1 * value AS grp_value
FROM (
SELECT id,
a,
b,
c,
DECODE(1,a,0,b,1,c,2) AS value
FROM table_name
)
)
ORDER BY id
其中,对于示例数据:
CREATE TABLE table_name (
id PRIMARY KEY,
a,
b,
c,
CHECK (a IN (0,1)),
CHECK (b IN (0,1)),
CHECK (c IN (0,1)),
CHECK (a+b+c = 1)
) AS
SELECT 1, 1, 0, 0 FROM DUAL UNION ALL
SELECT 2, 1, 0, 0 FROM DUAL UNION ALL
SELECT 3, 0, 1, 0 FROM DUAL UNION ALL
SELECT 4, 1, 0, 0 FROM DUAL UNION ALL
SELECT 5, 0, 1, 0 FROM DUAL UNION ALL
SELECT 6, 0, 0, 1 FROM DUAL UNION ALL
SELECT 7, 1, 0, 0 FROM DUAL UNION ALL
SELECT 8, 0, 1, 0 FROM DUAL UNION ALL
SELECT 9, 1, 0, 0 FROM DUAL UNION ALL
SELECT 10, 0, 1, 0 FROM DUAL UNION ALL
SELECT 11, 0, 0, 1 FROM DUAL UNION ALL
SELECT 12, 1, 0, 0 FROM DUAL UNION ALL
SELECT 13, 1, 0, 0 FROM DUAL UNION ALL
SELECT 14, 1, 0, 0 FROM DUAL UNION ALL
SELECT 15, 1, 0, 0 FROM DUAL UNION ALL
SELECT 16, 1, 0, 0 FROM DUAL UNION ALL
SELECT 17, 1, 0, 0 FROM DUAL UNION ALL
SELECT 18, 1, 0, 0 FROM DUAL UNION ALL
SELECT 19, 1, 0, 0 FROM DUAL UNION ALL
SELECT 20, 1, 0, 0 FROM DUAL
输出:
ID
A
B
C
ROW_AFTER_NEXT_MATCH
NUM_MATCHES
1
1
0
0
0
2
1
0
0
0
3
0
1
0
0
4
1
0
0
0
5
0
1
0
1
6
0
0
1
12
2
7
1
0
0
13
2
8
0
1
0
1
9
1
0
0
1
10
0
1
0
1
11
0
0
1
2
12
1
0
0
2
13
1
0
0
1
14
1
0
0
1
15
1
0
0
1
16
1
0
0
18
5
17
1
0
0
19
5
18
1
0
0
20
5
19
1
0
0
21
5
20
1
0
0
5
db<>fiddle here
这是我的table。它确实由 A、B 和 C 列组成。一次只有一列值为真。
我的任务是根据最近的五行来识别模式。
例如
我需要搜索整个 table 以查找这五个值何时重复。
如果重复,这些模式的下一个可用值是多少,并显示在该模式之后找到 A、B 和 C 值的次数。
如何在 SQL 中完成此操作?我正在使用甲骨文 11g。谢谢
您可以将 a, b, c
值转换为一个三进制数,然后计算该行和前 4 行的值,就好像这些行的三进制值包含一个 5 位数的三进制数,然后使用解析查找下一次出现并计算出现次数的函数:
SELECT id,
a,
b,
c,
CASE
WHEN grp_value IS NULL
THEN NULL
ELSE MIN(id) OVER (
PARTITION BY grp_value
ORDER BY id
ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING
) + 1
END AS row_after_next_match,
CASE
WHEN grp_value IS NULL
THEN 0
ELSE COUNT(id) OVER ( PARTITION BY grp_value )
END AS num_matches
FROM (
SELECT id,
a,
b,
c,
value,
81 * LAG(value,4) OVER ( ORDER BY id ) +
27 * LAG(value,3) OVER ( ORDER BY id ) +
9 * LAG(value,2) OVER ( ORDER BY id ) +
3 * LAG(value,1) OVER ( ORDER BY id ) +
1 * value AS grp_value
FROM (
SELECT id,
a,
b,
c,
DECODE(1,a,0,b,1,c,2) AS value
FROM table_name
)
)
ORDER BY id
其中,对于示例数据:
CREATE TABLE table_name (
id PRIMARY KEY,
a,
b,
c,
CHECK (a IN (0,1)),
CHECK (b IN (0,1)),
CHECK (c IN (0,1)),
CHECK (a+b+c = 1)
) AS
SELECT 1, 1, 0, 0 FROM DUAL UNION ALL
SELECT 2, 1, 0, 0 FROM DUAL UNION ALL
SELECT 3, 0, 1, 0 FROM DUAL UNION ALL
SELECT 4, 1, 0, 0 FROM DUAL UNION ALL
SELECT 5, 0, 1, 0 FROM DUAL UNION ALL
SELECT 6, 0, 0, 1 FROM DUAL UNION ALL
SELECT 7, 1, 0, 0 FROM DUAL UNION ALL
SELECT 8, 0, 1, 0 FROM DUAL UNION ALL
SELECT 9, 1, 0, 0 FROM DUAL UNION ALL
SELECT 10, 0, 1, 0 FROM DUAL UNION ALL
SELECT 11, 0, 0, 1 FROM DUAL UNION ALL
SELECT 12, 1, 0, 0 FROM DUAL UNION ALL
SELECT 13, 1, 0, 0 FROM DUAL UNION ALL
SELECT 14, 1, 0, 0 FROM DUAL UNION ALL
SELECT 15, 1, 0, 0 FROM DUAL UNION ALL
SELECT 16, 1, 0, 0 FROM DUAL UNION ALL
SELECT 17, 1, 0, 0 FROM DUAL UNION ALL
SELECT 18, 1, 0, 0 FROM DUAL UNION ALL
SELECT 19, 1, 0, 0 FROM DUAL UNION ALL
SELECT 20, 1, 0, 0 FROM DUAL
输出:
ID A B C ROW_AFTER_NEXT_MATCH NUM_MATCHES 1 1 0 0 0 2 1 0 0 0 3 0 1 0 0 4 1 0 0 0 5 0 1 0 1 6 0 0 1 12 2 7 1 0 0 13 2 8 0 1 0 1 9 1 0 0 1 10 0 1 0 1 11 0 0 1 2 12 1 0 0 2 13 1 0 0 1 14 1 0 0 1 15 1 0 0 1 16 1 0 0 18 5 17 1 0 0 19 5 18 1 0 0 20 5 19 1 0 0 21 5 20 1 0 0 5
db<>fiddle here