在 SQL table 的多个列中查找重复值并计算字符数

Finding duplicate values in multiple colums in a SQL table and count for chars

参考这个问题:

我有以下 table 结构:

id name1 name2 name3  ...
 1 Hans  Peter Frank
 2 Hans  Frank Peter
 3 Hans  Peter Frank
 4 Paul  Peter Hans
 .
 .
 .

我使用以下命令来显示重复项和计数:

SELECT COUNT(name1), name1, name2, name3 
FROM table 
GROUP BY name1, name2, name3 
HAVING (COUNT(name1) > 1) AND (COUNT(name2) > 1) AND (COUNT(name3) > 1)

这个命令给了我 2 的计数。我想知道第二行如何也可以算作重复。

很遗憾,原问题的解决方案 () 不适用于 char

首先在 CTE 中使用 UNION ALL 规范化 table,以便将 3 个名称中的每一个都放在单独的行中。
然后使用 ROW_NUMBER() window 函数,您可以按字母顺序排列 3 个名称,以便您可以按它们分组:

WITH cte(id, name) AS (
  SELECT id, name1 FROM tablename
  UNION ALL
  SELECT id, name2 FROM tablename
  UNION ALL
  SELECT id, name3 FROM tablename
)
SELECT COUNT(*) count, name1, name2, name3
FROM (
  SELECT id,
         MAX(CASE WHEN rn = 1 THEN name END) name1,
         MAX(CASE WHEN rn = 2 THEN name END) name2,
         MAX(CASE WHEN rn = 3 THEN name END) name3
  FROM (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY name) rn
    FROM cte
  )
  GROUP BY id
)
GROUP BY name1, name2, name3
HAVING COUNT(*) > 1;

另一种方法,它使用与您之前关于数值的问题类似的逻辑,使用字符串函数 REPLACE() 而不是 window 函数,但仅当每行中有 3 个名称时才有效不同:

SELECT COUNT(*) count,
       MIN(name1, name2, name3) name_1,
       REPLACE(
         REPLACE(
           REPLACE(name1 || ',' || name2 || ',' || name3, MIN(name1, name2, name3), ''), 
           MAX(name1, name2, name3), ''), ',', ''
       ) name_2,
       MAX(name1, name2, name3) name_3
FROM tablename 
GROUP BY name_1, name_2, name_3 
HAVING COUNT(*) > 1;

参见demo

不是特别漂亮,而是一种不同的方法来旋转列,然后将它们聚合为一个字符串并计算重复项。不幸的是,在 SQL Lite 中,group_concat 函数无法指定组内的任何顺序,这会强制进行另一层嵌套和 row_number .我猜这是 SQL lite!

的一部分

如果您想显示所有重复的变体,您可以删除 Seq 和过滤条件。

with cte as (
    select Duplicates, name1, name2, name3, 
      Row_Number() over(partition by Duplicates order by name1,name2,name3) Seq
    from (
      select count(*) over(partition by allnames) Duplicates, name1, name2, name3
      from t
      left join (
      select Id, group_concat(Dname) allNames
      from (
          select Id, Dname, row_number() over (partition by Id order by Dname) seq
              from (
                  select id, name1 Dname from t union all
                  select id, name2 from t union all
                  select id, name3 from t
              )x
       )x
     group by Id
     order by seq
     )d on d.id=t.id
   )d
)
select Duplicates, name1, name2, name3
from cte
where duplicates>1 and seq=1

Demo Fiddle

您只需要按所有列对行进行排序,对它们进行分组,计算重复项,并找到重复项最多的记录。在 SQL 中编写它是相当麻烦的,它使用包含 window 函数的嵌套查询。 SQL 语句很长而且难以阅读。另一种方法是从数据库中导出数据并在 Python 或 SPL 中处理它。 SPL,open-source Java 包,更容易集成到 Java 程序中并生成更简单的代码。它仅用三行代码就完成了任务:

A
1 =sqlite.query("select name1,name2,name3 from names")
2 =A1.group([#1,#2,#3].sort();~.len()).maxp(#2)
3 =create(count,name1,name2,name3).record([A2.#2,A2.#1(1),A2.#1(2),A2.#1(3)])