SQL - 只提取所有对一次
SQL - extracting all pairs only once
问题陈述:
- a table 有 N 列,其中 K 列用于确定行对的标准
- 这样一个涉及 K 列的标准可以简单地是如果列 c_1, c2, .. c_k 对于一对的两个不同行部分是相等的(标准本身是不相关的, 只有必须使用它的事实)
- 要求是提取所有潜在对,但只提取一次。这意味着,如果对于一行,有超过 2 个潜在的其他行可以根据上述标准形成一对,那么只需要提取一对
简单示例:
输入table:
A | B | C
x | y | z
w | y | z
u | y | z
u | v | z
v | v | z
条件:B 和 C 列必须相同,两行才能成为一对。
输出:
x | y | z
w | y | z
u | v | z
v | v | z
对于纯 SQL(或 Oracle 方言,如果特定功能有帮助)解决问题,您有什么提示?
对要成对匹配的行使用 COUNT()
分析函数分区:
SELECT A, B, C
FROM (
SELECT t.*,
COUNT(*) OVER (
PARTITION BY B, C
ORDER BY A
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS current_rn,
COUNT(*) OVER (
PARTITION BY B, C
ORDER BY A
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING
) AS next_rn
FROM table_name t
)
WHERE MOD( current_rn, 2 ) = 0
OR MOD( next_rn, 2 ) = 0;
输出:
A B C
- - -
u y z
w y z
u v z
v v z
如果可以使用window解析函数:
CREATE TABLE TT1 (A VARCHAR(4), B VARCHAR(4), C VARCHAR(4))
INSERT INTO TT1 VALUES ('x','y','z')
INSERT INTO TT1 VALUES ('w','y','z')
INSERT INTO TT1 VALUES ('u','y','z')
INSERT INTO TT1 VALUES ('u','v','z')
INSERT INTO TT1 VALUES ('v','v','z')
INSERT INTO TT1 VALUES ('k','w','z')
SELECT A.A, A.B, A.C
FROM
(SELECT *, ROW_NUMBER() OVER (PARTITION BY B,C ORDER BY A DESC) RN, COUNT(*) OVER (PARTITION BY B,C ) RC
FROM TT1) A
WHERE A.RN <=2 AND RC>1
输出:
A B C
---- ---- ----
v v z
u v z
x y z
w y z
问题陈述:
- a table 有 N 列,其中 K 列用于确定行对的标准
- 这样一个涉及 K 列的标准可以简单地是如果列 c_1, c2, .. c_k 对于一对的两个不同行部分是相等的(标准本身是不相关的, 只有必须使用它的事实)
- 要求是提取所有潜在对,但只提取一次。这意味着,如果对于一行,有超过 2 个潜在的其他行可以根据上述标准形成一对,那么只需要提取一对
简单示例:
输入table:
A | B | C x | y | z w | y | z u | y | z u | v | z v | v | z
条件:B 和 C 列必须相同,两行才能成为一对。
输出:
x | y | z w | y | z u | v | z v | v | z
对于纯 SQL(或 Oracle 方言,如果特定功能有帮助)解决问题,您有什么提示?
对要成对匹配的行使用 COUNT()
分析函数分区:
SELECT A, B, C
FROM (
SELECT t.*,
COUNT(*) OVER (
PARTITION BY B, C
ORDER BY A
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS current_rn,
COUNT(*) OVER (
PARTITION BY B, C
ORDER BY A
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 FOLLOWING
) AS next_rn
FROM table_name t
)
WHERE MOD( current_rn, 2 ) = 0
OR MOD( next_rn, 2 ) = 0;
输出:
A B C
- - -
u y z
w y z
u v z
v v z
如果可以使用window解析函数:
CREATE TABLE TT1 (A VARCHAR(4), B VARCHAR(4), C VARCHAR(4))
INSERT INTO TT1 VALUES ('x','y','z')
INSERT INTO TT1 VALUES ('w','y','z')
INSERT INTO TT1 VALUES ('u','y','z')
INSERT INTO TT1 VALUES ('u','v','z')
INSERT INTO TT1 VALUES ('v','v','z')
INSERT INTO TT1 VALUES ('k','w','z')
SELECT A.A, A.B, A.C
FROM
(SELECT *, ROW_NUMBER() OVER (PARTITION BY B,C ORDER BY A DESC) RN, COUNT(*) OVER (PARTITION BY B,C ) RC
FROM TT1) A
WHERE A.RN <=2 AND RC>1
输出:
A B C
---- ---- ----
v v z
u v z
x y z
w y z