【问题标题】:Finding same values in different rows and different columns in one table SQL在一个表的不同行和不同列中查找相同的值 SQL
【发布时间】:2019-12-11 00:03:23
【问题描述】:

我有一张有几十列和超过 200 万行的大表。 不同行的某些值可能相同,并且在同一个表的不同列和不同行中重复。我怎样才能找到它们?

示例:我需要找到所有这些。但是我不知道哪个是 VALUE 'THIS'。

id  |  c1  |  c2  |  c3  |  c4  |  c5  |  
----+------+------+------+------+------+-------  
1   | THIS |   x  |   y  |   z  | NULL |  
2   | NULL | THIS |   f  |   b  |   c  |
3   | NULL |   h  | NULL |   p  | THIS |   

找到它们后,我需要合并它们并将所有 THIS 移到 c1 列中,替换 NULL。

有什么好主意吗? 谢谢

【问题讨论】:

  • 也许我不明白你。您想说所有其他值(如示例中的 x、y、z、f、b、c、h、p 在所有列和行中都是唯一的?如果您正在寻找特定于数据库的解决方案,请使用您使用的数据库。
  • 数据库是什么?
  • 您好,谢谢。新人的经典。是 MS SQL。
  • 皮洛萨,正确的。除了我在示例 THIS 中命名的那些可以不同或重复的值之外,所有其他值在列和行中都是唯一的。都是名字,但不知道哪些名字不知道哪些名字是重复的。

标签: sql sql-server duplicates


【解决方案1】:

真的想不出比愚蠢的 SQL 更好的东西了:

update table set c1='THIS' where c2='THIS' or c3='THIS' or c4='THIS' or ...

大概你可以使用编辑器快速生成查询,然后复制并粘贴到 mysql、psql 或其他任何东西中。

【讨论】:

  • 谢谢。但是 THIS 的值是未知的。我用 THIS 为潜在的重复值赋值。希望这可以澄清。
【解决方案2】:

您可以从INFORMATION_SCHEMA.COLUMNS 读取列名并动态编写 SQL。

我使用The Impaler's approach 来获取重复值。如果您的 SQL Server 的版本是 2017 或更高版本,您可能希望使用 STRING_AGG 而不是 SET @p = ISNULL(@p + '...', '') + ... 以获得更易读的代码。

DECLARE
    @p1 NVARCHAR(MAX),
    @p2 NVARCHAR(MAX),
    @sql NVARCHAR(MAX)

SELECT
    @p1 = ISNULL(@p1 + ' AS duplicate FROM your_table UNION ALL SELECT ', '') + COLUMN_NAME,
    @p2 = ISNULL(@p2 + ', ', '') + COLUMN_NAME
FROM
    INFORMATION_SCHEMA.COLUMNS
WHERE
    TABLE_NAME = 'your_table'
    AND COLUMN_NAME NOT IN('id', 'c1')

SET @sql = '
    WITH duplicates AS (
        SELECT t.duplicate FROM (SELECT ' + @p1 + ' FROM your_table) t WHERE t.duplicate IS NOT NULL GROUP BY t.duplicate HAVING COUNT(*) > 1
    )
    UPDATE your_table
        SET
            c1 = d.duplicate
        FROM
            your_table t
            INNER JOIN duplicates d
                ON t.c1 IS NULL
                AND d.duplicate IN(' + @p2 + ')'

EXEC(@sql)

【讨论】:

    【解决方案3】:

    好吧,关于查找重复值的第一部分可以通过以下查询来完成。根据表格的列数调整它:

    select c
    from (
      select c1 as c from t
      union all select c2 from t
      union all select c3 from t
      union all select c4 from t
      union all select c5 from t
    ) x
    group by c
    having count(*) > 1
    

    重复使用上面的查询,您可以得到每个值在哪些行中重复。你没有提到你正在使用哪个数据库,所以我会给你一个在 PostgreSQL 中工作的 CTE 查询。其他数据库可能需要进行细微更改:

    with
    v as (
      select id, c1 as c from t
      union all select id, c2 from t
      union all select id, c3 from t
      union all select id, c4 from t
      union all select id, c5 from t
    ),
    d as (
      select c
      from v
      group by c
      having count(*) > 1
    )
    select
      v.c, v.id
    from d
    join v on v.c = d.c
    order by v.c, v.id
    

    【讨论】:

    • 谢谢。但该表有 200 多列。任何我不必全部输入的解决方案?
    • 穿刺者。这似乎有效,但我怎样才能找到它们在哪些行/ID 中以便我可以合并它们?
    • 添加了额外的信息来识别重复值的行。
    猜你喜欢
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-19
    • 1970-01-01
    相关资源
    最近更新 更多