删除 SQL 中其他行的子集行

Remove subset rows of other rows in SQL

下面这个 table 包括 ID 和五个指标列:x1, ..., x5:

我需要根据这个逻辑删除重复项:

对于每个 ID,我们查看 x1、...、x5 的值,然后删除其他行的子集。例如,对于 ID=1,第 3 行是第 2 行的子集,因此我们删除第 3 行。此外,第 4 行不是第 2 行的子集,因此我们保留它。

这是 table 的预期最终视图:

首先将 5 列的所有值连接起来,这样您就可以得到一个二进制字符串,例如“100101”,它可以转换为以 10 为基数的数字,例如别名 value,函数 CONV() .

假设 table 中没有重复的行,正如您在评论中提到的那样,行 #X 应被视为另一行的子集 #Y if bitwise OR 两行的 value 之间的结果 returns #Y 的 value :

SELECT t1.*
FROM tablename t1
WHERE NOT EXISTS (
  SELECT *
  FROM tablename t2
  WHERE t2.ID = t1.ID 
    AND (t1.x1, t1.x2, t1.x3, t1.x4, t1.x5) <>
        (t2.x1, t2.x2, t2.x3, t2.x4, t2.x5)
    AND CONV(CONCAT(t1.x1, t1.x2, t1.x3, t1.x4, t1.x5), 2, 10) |
        CONV(CONCAT(t2.x1, t2.x2, t2.x3, t2.x4, t2.x5), 2, 10) =
        CONV(CONCAT(t2.x1, t2.x2, t2.x3, t2.x4, t2.x5), 2, 10)
);

或者,对于 MySql 8.0+:

WITH cte AS (
  SELECT *, CONV(CONCAT(x1, x2, x3, x4, x5), 2, 10) value
  FROM tablename
)
SELECT t1.ID, t1.x1, t1.x2, t1.x3, t1.x4, t1.x5
FROM cte t1
WHERE NOT EXISTS (
  SELECT *
  FROM cte t2
  WHERE t2.ID = t1.ID 
    AND t2.value <> t1.value
    AND t1.value | t2.value = t2.value
);

如果要删除子集行,请像这样使用 table 的自联接:

DELETE t1
FROM tablename t1 INNER JOIN tablename t2
ON t2.ID = t1.ID
AND (t1.x1, t1.x2, t1.x3, t1.x4, t1.x5) <>
    (t2.x1, t2.x2, t2.x3, t2.x4, t2.x5)
AND CONV(CONCAT(t1.x1, t1.x2, t1.x3, t1.x4, t1.x5), 2, 10) |
    CONV(CONCAT(t2.x1, t2.x2, t2.x3, t2.x4, t2.x5), 2, 10) =
    CONV(CONCAT(t2.x1, t2.x2, t2.x3, t2.x4, t2.x5), 2, 10);

参见demo