【问题标题】:Finding Duplicates: GROUP BY and DISTINCT giving different answers查找重复项:GROUP BY 和 DISTINCT 给出不同的答案
【发布时间】:2019-05-31 19:58:12
【问题描述】:

我已经查看了有关 group by 和 distinct 的所有问题,它们在允许聚合函数方面似乎有所不同,但没有一个回答我的问题......所以这里是......

我有一个包含 126266 行数据的数据库表,每个完整的行都应该是唯一的,但我没有使用行号。 我试图在这个表中找到所有重复的值(因为我知道它们存在),然后删除它们。没有一列是聚合。

表:

CREATE TABLE [dbo].[DBAScanResults](
    [ScanNumber] [float] NOT NULL,
    [DB_ID] [bigint] NOT NULL,
    [PluginID] [bigint] NOT NULL,
    [PluginID_Version] [bigint] NOT NULL,
    [Result] [nvarchar](50) NULL,
    [ActualValue] [nvarchar](max) NULL

我有外键:ScanNumber、DB_ID、PluginID_Version。每个相关的主键都在不同的表上。 (所以我的数据库目前是四个表)

如果我进行分组,它会给我 12745 行,这是我的重复行:

Select top 1000000 [ScanNumber]
      ,[DB_ID]
      ,[PluginID]
      ,[PluginID_Version]
      ,[Result]
      ,[ActualValue]
  FROM [ITSecMaster].[dbo].[DBAScanResultsNew]
  group by [ScanNumber]
      ,[DB_ID]
      ,[PluginID]
      ,[PluginID_Version]
      ,[Result]
      ,[ActualValue]
      HAVING COUNT(*) >1 

如果我做一个独特的( Select distinct * from [dbo].[DBAScanResults]),它会给我 78,871 行,我猜这是我唯一没有重复的行数。我这里的问题是 12745+78871 不等于 126226 ...

那么到底哪一个是正确的?我有 12745 个重复项还是 47,355 个重复项? 一旦我确定了哪个是正确的,我就需要从表中删除重复的值......通常我会这样做以删除带有 fk 的值,但我无法为多个 fks 获得正确的语法跨越 2 张以上的桌子。

DELETE a   
FROM DBAScanResults a 
INNER JOIN DBAScanDate b 
ON a.ScanNumber = b.ScanNumber 
WHERE (expression) 

对此的任何帮助将不胜感激。

提前致谢!

【问题讨论】:

  • 请告诉我们从表中删除记录的逻辑是什么。您要删除所有个重复记录,还是保留其中的 1(或 2)条?
  • 我想删除除 1 个之外的所有重复值。所以在你的` text ---- A B B C C C `表中,我希望最终输出是` text ---- A B C `
  • 你的数据库是什么? SQL Server、Oracle 还是其他?
  • SQL...我在帖子中使用了 SQL 标记...抱歉没有更具体地指出它...
  • 啊。抱歉@a_horse_with_no_name - 但感谢您的澄清。它是 SQL Server....

标签: sql sql-server duplicates


【解决方案1】:

你的计数逻辑是错误的,我的也是,直到我想出了一个简单的例子来更好地理解你的问题。想象一个只有一列的简单表格,text

text
----
A
B
B
C
C
C

正如预期的那样,运行 SELECT COUNT(*) 只会产生 6 条记录。 SELECT DISTINCT textA,B,C 返回 3 条记录。最后,SELECT textHAVING COUNT(*) > 1 仅返回两条记录,分别用于 BC 组。

这些数字都没有加起来。这里的问题是,除了重复的记录之外,不同的选择还会返回重复的记录。此外,给定的重复记录可能出现更多次。你目前的比较有点像苹果和橘子。

编辑:

如果您想删除六列表中的所有重复项,只保留所有列中的一条不同记录,请尝试使用可删除的 CTE:

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY ScanNumber, DB_ID, PluginID,
                                        PluginID_Version, Result, ActualValue
                               ORDER BY (SELECT NULL)) rn
    FROM DBAScanResults
)

DELETE
FROM cte
WHERE rn > 1;

【讨论】:

  • 当然!我从来没有想过一行会出现超过 2 行......所以我完全唯一的非重复表是 78,871 - distinct 返回的行是我唯一的表。正确的?你能帮忙看看我现在如何删除distinct 语句中未返回的所有内容吗?
  • @BeckyG 是的,SELECT DISTINCT 为您提供 所有 行并删除了重复项。但是,这包括一开始就没有重复的行。
  • 好的,这基本上就是我想要的 - 我只需要弄清楚如何删除没有在不同选择中返回的所有内容然后......
  • 您的要求没有意义。请告诉我们决定记录是否被删除或保留的逻辑。
  • 最终目标:我想要只有唯一值的表 - 所以表中应该有 78,871 行。因此,在存在重复项的情况下,除了 1 个重复项之外,所有重复项都会被删除。
猜你喜欢
  • 1970-01-01
  • 2018-06-28
  • 1970-01-01
  • 2018-10-27
  • 2012-05-25
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多