如何在多列中找到重复项?

Nim*_*sky 87 sql sql-server sql-server-2008

所以我想做下面的sql代码:

select s.id, s.name,s.city 
from stuff s
group by s.name having count(where city and name are identical) > 1
Run Code Online (Sandbox Code Playgroud)

要产生以下内容,(但忽略只有名称或仅匹配城市的地方,它必须在两列上):

id      name  city   
904834  jim   London  
904835  jim   London  
90145   Fred  Paris   
90132   Fred  Paris
90133   Fred  Paris
Run Code Online (Sandbox Code Playgroud)

Mic*_*aga 123

id对重复namecity:

select s.id, t.* 
from [stuff] s
join (
    select name, city, count(*) as qty
    from [stuff]
    group by name, city
    having count(*) > 1
) t on s.name = t.name and s.city = t.city
Run Code Online (Sandbox Code Playgroud)

  • 如果值可能包含```null```那么(除非我遗漏了什么)你需要将它改为````CROSS JOIN```(完全笛卡尔积)然后添加一个```WHERE ```子句如:```WHERE((s.name = t.name)OR(s.name为null,t.name为null))AND((s.city = t.city)OR(s .city为null,t.city为null))``` (2认同)

小智 43

 SELECT name, city, count(*) as qty 
 FROM stuff 
 GROUP BY name, city HAVING count(*)> 1
Run Code Online (Sandbox Code Playgroud)

  • 这样,你就无法知道每行的 id。 (2认同)
  • @yoyo 你的建议给出了一个错误;请建议完整的SQL,不会给出错误。 (2认同)

ssa*_*ndo 8

像这样的东西可以解决问题.不了解性能,所以做一些测试.

select
  id, name, city
from
  [stuff] s
where
1 < (select count(*) from [stuff] i where i.city = s.city and i.name = s.name)
Run Code Online (Sandbox Code Playgroud)


小智 6

这篇文章的游戏有点晚了,但我发现这种方式非常灵活/高效

select 
    s1.id
    ,s1.name
    ,s1.city 
from 
    stuff s1
    ,stuff s2
Where
    s1.id <> s2.id
    and s1.name = s2.name
    and s1.city = s2.city
Run Code Online (Sandbox Code Playgroud)


Use*_*ady 5

使用count(*) over(partition by...)提供了一种简单有效的方法来查找不需要的重复,同时还列出了所有受影响的行和所有想要的列:

SELECT
    t.*
FROM (
    SELECT
        s.*
      , COUNT(*) OVER (PARTITION BY s.name, s.city) AS qty
    FROM stuff s
    ) t
WHERE t.qty > 1
ORDER BY t.name, t.city
Run Code Online (Sandbox Code Playgroud)

尽管最新的RDBMS版本支持count(*) over(partition by...) MySQL V 8.0引入了“窗口函数”,如下所示(在MySQL 8.0中)

CREATE TABLE stuff(
   id   INTEGER  NOT NULL
  ,name VARCHAR(60) NOT NULL
  ,city VARCHAR(60) NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
INSERT INTO stuff(id,name,city) VALUES 
  (904834,'jim','London')
, (904835,'jim','London')
, (90145,'Fred','Paris')
, (90132,'Fred','Paris')
, (90133,'Fred','Paris')

, (923457,'Barney','New York') # not expected in result
;
Run Code Online (Sandbox Code Playgroud)
SELECT
    t.*
FROM (
    SELECT
        s.*
      , COUNT(*) OVER (PARTITION BY s.name, s.city) AS qty
    FROM stuff s
    ) t
WHERE t.qty > 1
ORDER BY t.name, t.city
Run Code Online (Sandbox Code Playgroud)
    id | 名称| 城市| 数量
-----:| :--- | :----- | -:
 90145 | 弗雷德| 巴黎| 3
 90132 | 弗雷德| 巴黎| 3
 90133 | 弗雷德| 巴黎| 3
904834 | 吉姆| 伦敦| 2
904835 | 吉姆| 伦敦| 2

db <> 在这里拨弄

窗口功能。 MySQL现在支持窗口函数,对于查询中的每一行,都使用与该行相关的行来执行计算。这些包括诸如RANK(),LAG()和NTILE()之类的函数。另外,现在可以将几个现有的聚合函数用作窗口函数;例如SUM()和AVG()。有关更多信息,请参见第12.21节“窗口函数”


小智 5

SELECT Feild1, Feild2, COUNT(*)
FROM table name
GROUP BY Feild1, Feild2
HAVING COUNT(*)>1
Run Code Online (Sandbox Code Playgroud)

这会给你所有的答案。