【问题标题】:SQL - Way to find duplicate fields within multiple rows?SQL - 在多行中查找重复字段的方法?
【发布时间】:2016-11-21 07:27:58
【问题描述】:

我想知道是否有办法返回部分行的重复项。

IDTable 设置:

ID# | Customer  | EventID#
1   | Steve     | 123
2   | Steve     | 123
3   | John      | 987
4   | John      | 924

由于史蒂夫和 123 一起出现了两次,我想将其视为“重复”,即使他们有两个不同的 ID#。如果有“重复”,理想情况下我只想返回列:ID#、Customer & EventID#。所以对于上面的IDTable例子,只返回:

1   | Steve | 123
2   | Steve | 123

通过运行以下命令,它分别计算每个 ID + Customer + EventID# 并将所有 Count 值返回为 1(我使用的是 SQL Server 2008):

SELECT ID#, Customer, EventID#, COUNT({fn CONCAT(Customer,EventID#)})
FROM IDTable
GROUP BY ID#, Customer, EventID#
HAVING COUNT({fn CONCAT(Customer,EventID#)}) > 1

如果我从 Select 中取出 ID#,它会起作用,但我们将不知道 ID# 是什么。

编辑: 我正在加入来自其他表的选择列。为了简单起见,我最初将这些排除在外,因为在尝试应用下面的解决方案时我感到困惑。道歉!以下是更符合我正在使用的内容:

SELECT A.ID#, C.Customer, E.EventID#
FROM IDTable A
INNER JOIN CustomerTable C
   ON C.AccountID = A.AccountID
INNER JOIN EventTable E
   ON E.AccountType = C.AccountType
WHERE C.StatusID = 'Active'

【问题讨论】:

  • 用您正在使用的数据库标记您的问题。

标签: sql sql-server count duplicates


【解决方案1】:

Self-Join 应该可以解决问题:

SELECT     A.ID#, A.Customer, A.EventID#
FROM       Table A
INNER JOIN Table A2 ON A.Customer = A2.Customer 
                   AND A.EventID# = A2.EventID# 
                   AND A.ID# <> A2.ID#

编辑您的联接:

您仍然可以使用自联接,只是像这样使用派生表:

SELECT     A.ID#, A.Customer, A.EventID#
FROM       (SELECT ID#, Customer, EventID#
            FROM IDTable A
            INNER JOIN CustomerTable C ON C.AccountID = A.AccountID
            INNER JOIN EventTable E ON E.AccountType = C.AccountType
            WHERE C.StatusID = 'Active') A
INNER JOIN (SELECT ID#, Customer, EventID#
            FROM IDTable A
            INNER JOIN CustomerTable C ON C.AccountID = A.AccountID
            INNER JOIN EventTable E ON E.AccountType = C.AccountType
            WHERE C.StatusID = 'Active') A2 ON A.Customer = A2.Customer 
                                           AND A.EventID# = A2.EventID# 
                                           AND A.ID# <> A2.ID#

#TEMP清理干净:

SELECT A.ID#, C.Customer, E.EventID#
INTO #TEMP
FROM IDTable A
INNER JOIN CustomerTable C
   ON C.AccountID = A.AccountID
INNER JOIN EventTable E
   ON E.AccountType = C.AccountType
WHERE C.StatusID = 'Active'
;

SELECT     A.ID#, A.Customer, A.EventID#
FROM       #TEMP A
INNER JOIN #TEMP A2 ON A.Customer = A2.Customer 
                   AND A.EventID# = A2.EventID# 
                   AND A.ID# <> A2.ID#

【讨论】:

  • 有趣。所以本质上是一系列连接在一起的子查询?我会试一试...
  • 我不会那样做。您可以先 SELF JOIN,然后才能与 CustomerTable 和 EventTable JOIN。
  • @bojackh 没错。实际上,如果您要经常使用它,最简洁的方法是创建一个临时表或 CTE 并以这种方式进行自联接(本质上是第一个查询)。派生表做同样的事情,但它们需要 SQL 来运行两次查询。旁注,如果这些列存在于多个表中,您可能需要也可能不需要弄乱内部别名。
  • @caiohamamura 不,你不能......每个表中的列都是自连接谓词所必需的。
  • 但是这两个谓词都将仅依赖于 AccountID,因为 AccountID 将加入具有 AccountType 的客户。所以它们都只依赖于 AccountID。
【解决方案2】:

大多数版本的 SQL 都支持窗口函数。解决这个问题的最简单方法是:

select id, customer, eventid#
from (select i.*, count(*) over (partition by customer, eventid#) as cnt
      from idtable i
     ) i
where cnt > 1;

【讨论】:

  • 我实际上是从其他表中加入客户和 EventID。因此,当我尝试运行此程序时,在“分区依据”之后出现错误“无法绑定多部分标识符“C.Customer”。让我知道是否需要编辑初始查询以合并联接;为简单起见,将它们省略了,但现在看起来我需要添加它们..
  • @bojackh。 . .此解决方案中没有名为c 的表别名,因此完全不清楚这会如何产生错误。
【解决方案3】:
SELECT i.*
FROM
    IDTable i
    INNER JOIN 
       (SELECT Customer, EventID#
       FROM IDTable
       GROUP BY ID#, Customer, EventID#
       HAVING COUNT(*) > 1) t
    ON i.Customer = t.Customer
    AND i.EventId# = t.EventId#

可能还有其他方法可以做到这一点,如果您标记您的特定 rdbms(sql-server、oracle、mysql 等),我相信您会得到其他答案,但这是一种方法,即使用您的查询(没有 ID 列)以识别重复项,然后通过内部连接将其匹配回原始表。

【讨论】:

  • 嗨,我编辑了我的初始查询以包括我从 select 语句中获得的初始连接。试图弄清楚如何将您的解决方案与我编辑的查询结合起来。
  • 您使用的是哪个 rdbms? mysql?微软的sql服务器?甲骨文????上面有很多很好的答案,但根据您对所使用技术的回答,我们所有人都可以使我们的答案更简单、更容易理解。
  • MS SQL 服务器。谢谢
  • 使用 gordon 的答案,您可以在子选择中执行所有连接等操作。 SQL 将解释它几乎就像我建议的那样,只是更少的代码和更清洁。
【解决方案4】:

根据@Aaron_D 的回答,我不会加入子查询,而是您可以这样做:

SELECT A.ID#, C.Customer, E.EventID#
FROM IDTable A
INNER JOIN IDTable B ON A.ID# = B.ID#
                    AND A.AccountID <> B.AccountID
INNER JOIN CustomerTable C
   ON C.AccountID = A.AccountID
INNER JOIN EventTable E
   ON E.AccountType = C.AccountType
WHERE C.StatusID = 'Active'

由于 CustomerTable 和 EventTable 都是从 AccountID 派生的最后一个实例,因此它可以正常工作并且速度会更快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    相关资源
    最近更新 更多