繁体   English   中英

两列分组在另一列上的区别

[英]Distinct of two columns grouping on another column

我正在尝试对SQL Server的另一列上分组的两列上的重复值数量进行计数。

以下是我正在研究的示例方案。

    DECLARE @mytable TABLE (CampName varchar(10),ID VARCHAR(10),ListName varchar(10))
    INSERT INTO @mytable
            ( CampName, ID, ListName )
    VALUES  ( 'A',   'X',   'Y' ), ( 'A',   'X',   'Y' ), 
            ( 'A',   'Y',   'Z' ), ( 'A',   'Y',   'Z' ),
            ( 'A',   'Y',   'Z' ), ( 'A',   'P',   'Q' ),
            ( 'B',   'X',   'Y' ), ( 'B',   'X',   'Y' ), 
            ( 'B',   'Y',   'Z' ), ( 'B',   'Y',   'Z' ),
            ( 'B',   'Y',   'Z' ), ( 'B',   'P',   'Q' ),
            ( 'B',   'R',   'S' ), ( 'B',   'R',   'S' )

这将产生下表。

 CampName   ID  ListName
-------------------------------------
      A     X     Y
      A     X     Y -- Duplicate Record
      A     Y     Z
      A     Y     Z -- Duplicate Record
      A     Y     Z -- Duplicate Record
      A     P     Q
      B     X     Y 
      B     X     Y -- Duplicate Record
      B     Y     Z
      B     Y     Z -- Duplicate Record
      B     Y     Z -- Duplicate Record
      B     P     Q
      B     R     S
      B     R     S -- Duplicate Record

我需要如下输出:

CampName   dupcount
-------------------
A            3
B            4

基本上,我需要弄清楚每个CampName的重复数(ID,ListName),无论重复值是多少。

让我知道是否可以在这方面澄清其他问题。 任何帮助将不胜感激。

您可以使用以下查询:

SELECT CampName, SUM(cnt) AS dupcount
FROM (
  SELECT CampName, COUNT(*) - 1 AS cnt
  FROM @mytable
  GROUP BY CampName, ID, ListName
  HAVING COUNT(*) > 1) AS t
GROUP BY CampName

内部查询使用HAVING子句过滤掉非重复的条目。 它还计算每个ID, ListName的重复记录数。 外部查询仅对重复项的数量求和。

这是获得所需结果的一种简单方法:

select t.campname, count(*) - count(distinct t.listname) as num_duplicates
from @mytable t
group by t.campname;

逻辑是count(*)对所有行进行计数。 count(distinct)计算不重复列表的数量。 区别在于重复项的数量。

编辑:

Giorgios提出了一个很好的观点。 但是,数据看起来像idname包含相同的信息,因此似乎只需要一个。 如果必须同时使用两者,则许多数据库将允许您执行以下操作:

select t.campname, count(*) - count(distinct t.id, t.listname) as num_duplicates
from @mytable t
group by t.campname;

但不是SQL Server。 而是将它们串联在一起:

select t.campname,
       count(*) - count(distinct concat(t.id, ':', t.listname)) as num_duplicates
from @mytable t
group by t.campname;

我认为,需要从每个CampName组的总数中减去ID ListName组合的不同数量,以获得正确的结果。

SELECT t.CampName,
       COUNT(*) - COUNT(DISTINCT 'ColOne' + ID + 'ColTwo' + ListName) AS dupcount
FROM yourTable t
GROUP BY CampName

该查询采用了一种技巧,即将IDListName列(它们都是文本)串联起来,以有效地形成伪组。 这样做的需要是DISTINCT仅适用于单个列,但是您需要考虑两个列。

参考: Quora:在SQL中,如何计算多列的DISTINCT?

这个问题有些含糊。

如果您认为所有IDListName组合始终相等,则以下查询对您有效:

您只需在COUNT内部使用DISTINCT

SELECT CampName, COUNT(DISTINCT ListName) UniqueCount
FROM @mytable
GROUP BY CampName

如果您怀疑组合可能并非一直都相等,则需要考虑对IDListName列的组合进行计数。

假设串联运算符| 这将不会出现在两列中的任何一列中。

SELECT CampName, COUNT(DISTINCT ID+'|'+ListName) UniqueCount
FROM @mytable
GROUP BY CampName

如果您担心要计算重复的行数

SELECT CampName, COUNT(*) - COUNT(DISTINCT ID+'|'+ListName) dupCount
FROM @mytable
GROUP BY CampName

我认为另一种选择

;WITH Temp AS
(
    SELECT CampName, ID, ListName, COUNT(*) UniqueCount 
    FROM @mytable
    GROUP BY CampName, ID, ListName
)
SELECT CampName, COUNT(UniqueCount) count 
FROM Temp
GROUP BY CampName

您还可以使用CONCAT检索相同的结果,它更可靠

SELECT CampName, 
    COUNT(ListName)-COUNT(DISTINCT CONCAT(id,ListName)) tot 
FROM #tmp 
GROUP BY CampName 

尝试这样的事情,分析SELECT语句,WITH子句对逻辑并不重要:

WITH input_data AS (
  SELECT 'X' AS x, 'Y' AS y FROM DUAL
  UNION ALL
  SELECT 'X' AS x, 'Y' AS y FROM DUAL
  UNION ALL
  SELECT 'X' AS x, 'A' AS y FROM DUAL
)
SELECT input_data.*, COUNT(*) OVER (PARTITION BY x, y) - 1 AS numer_duplicates
FROM input_data
;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM