1

类似:如何删除表中的重复行

我有一种感觉,这是不可能的,我将不得不以乏味的方式去做,但我会看看你们要说什么。

我有一张相当大的桌子,大约有 400 万行和 50 多列。它有一个应该是唯一的列,Episode。不幸的是,Episode并不是唯一的——这背后的逻辑是偶尔会改变行中的其他字段,尽管 Episode 会重复。但是,实际上有一个唯一的列,Sequence。

我想尝试识别具有相同剧集编号但它们之间有所不同(除了序列)的行,所以我可以找出这种情况发生的频率,以及是否值得允许,或者我应该只删除这些行并忽略可能的轻微差异。

我希望创建一个显示情节编号的表格,并为每个表格列创建一个列,确定双方的值,它们是不同的:

SELECT Episode, 
       CASE WHEN a.Value1<>b.Value1 
            THEN a.Value1 + ',' + b.Value1 
            ELSE '' END AS Value1,
       CASE WHEN a.Value2<>b.Value2 
            THEN a.Value2 + ',' + b.Value2 
            ELSE '' END AS Value2
FROM Table1 a INNER JOIN Table1 b ON a.Episode = b.Episode
WHERE a.Value1<>b.Value1
      OR a.Value2<>b.Value2

(这可能充满了漏洞,但我希望突出显示更改的值的想法得以实现。)

不幸的是,对五十列进行这样的查询非常痛苦。显然,如果只使用一次,它并不一定要坚如磐石,但同时,代码复制的越多,就越有可能遗漏一些东西。据我所知,我不能只搜索 DISTINCT,因为 Sequence 是不同的,并且同一行会以不同的方式弹出。

有没有人有可能有帮助的查询或功能?会输出类似于上述查询结果的东西,还是不同的解决方案?正如我所说,现在我并不是真的要删除重复项,只是识别它们。

4

6 回答 6

1

采用:

  SELECT DISTINCT t.*
    FROM TABLE t
ORDER BY t.episode --, and whatever other columns

DISTINCT只是写 aGROUP BY涉及所有列的简写。在这种情况下,按所有列分组将显示与情节列关联的所有唯一记录。因此,存在无法准确计算重复项的风险,但您将拥有这些值,因此您可以决定在达到该点时删除哪些内容。

50 列很多,但设置 ORDER BY 将允许您查看列表。如果您不想构造 ORDER BY,另一种选择是将数据导出到 Excel,并使用 Excel 的排序。

更新 我没有发现序列列将是一个唯一值,但在这种情况下,您必须提供您想要查看的所有列的列表。IE:

  SELECT DISTINCT t.episode, t.column1, t.column2 --etc.
    FROM TABLE t
ORDER BY t.episode --, and whatever other columns

没有任何符号可以让您使用t.* but not this one column. 一旦从输出中省略了序列列,重复项就会变得明显。

于 2009-11-25T04:17:35.087 回答
1

您可以这样做,而不是输入所有 50 列:

select column_name from information_schema.columns where table_name = 'your table name'

然后将它们粘贴到按除序列以外的所有列分组的查询中,并按计数 > 1 过滤:

select 
  count(episode)
, col1
, col2
, col3
, ...
from YourTable
group by
  col1
, col2
, col3
, ...
having count(episode) > 1

这应该为您提供具有相同剧集编号的所有行的列表。(但既不是序列也不是剧集编号本身)。这就是问题所在:您需要将此结果集加入到 YourTable 中除序列和剧集之外的所有列上,因为您在此处没有这些列。

这里是我喜欢使用 SQL 生成更多 SQL 的地方。这应该让你开始:

select 't1.' + column_name + ' = t2.' + column_name
from information_schema.columns where table_name = 'YourTable'

您将这些连接参数插入到此查询中:

select * from YourTable t1 
inner join (
select 
      count(episode) 'epcount'
    , col1
    , col2
    , col3
    , ...
    from YourTable
    group by
      col1
    , col2
    , col3
    , ...
    having count(episode) > 1
) t2 on 

...plug in all those join parameters here...
于 2009-11-25T06:25:14.767 回答
0
select count distinct ....

应该告诉你而不必猜测。您可以通过查看表定义来获取列,以便复制/粘贴非序列列。

于 2009-11-25T04:06:46.967 回答
0

我认为这样的事情是你想要的:

select *
from t
where t.episode in (select episode from t group by episode having count(episode) > 1)
order by episode

这将给出具有重复剧集的所有行。非重复行应该相当明显地突出。

当然,如果您可以访问某种脚本,您可以编写一个脚本来为您生成查询。这似乎很简单。(即describe t遍历所有字段)。

此外,您的查询应该具有某种排序,例如FROM Table1 a INNER JOIN Table1 b ON a.Episode = b.Episode AND a.Sequence < b.Sequence,否则您将得到重复的非重复项。

于 2009-11-25T04:33:45.990 回答
0

Ponies 引发的一个相对简单的解决方案:

SELECT  t.*
FROM    Table t
    INNER JOIN ( SELECT episode
                 FROM   Table
                 GROUP BY Episode
                 HAVING COUNT(*) > 1
               ) AS x ON t.episode = x.episode

然后,复制粘贴到 Excel 中,并将其用作整个结果集的条件突出显示:

=AND($C2=$C1,A2<>A1)

C列是情节。这样,当数据与上面的行不同时(只要两行的情节值相同),您就会获得视觉突出显示。

于 2009-11-25T04:39:44.683 回答
0

为每一行生成并存储一个哈希键,旨在使哈希值反映您对相同性的定义。根据行的复杂性,更新哈希可能是修改行的简单触发器。

查询哈希键的重复项,这是您“很可能”相同的行。

于 2009-11-25T06:31:41.977 回答