【问题标题】:How to write a MySQL select query for obtaining duplicates in select columns but unique in another如何编写 MySQL 选择查询以获取选择列中的重复项但在另一个列中是唯一的
【发布时间】:2018-09-06 12:41:00
【问题描述】:

假设我有一个包含 3 列 A、B、C 的表。我想要一个结果集,它表示那些条目对于 A 或 B 具有多个/重复条目但对于 C 具有唯一条目。

我知道 GROUP BY 子句在这种情况下会派上用场,但它似乎比这更复杂。

例如: 比如说,一个包含以下列的客户信息的表: 1)身份证 2)电话 3)电子邮件 4)账户

获取那些多次出现相同电话或电子邮件但属于不同帐户的 ID。例如,对于原始表中的以下条目:

1) ID:12 |电话:111-111-1111 |电子邮件:johnc@email.com |帐号:2

2) ID:14 |电话:111-111-1111 |电子邮件:jcena@gmail.com |帐号:5

3) ID:15 |电话:123-234-7890 |电子邮件:jdoe@email.com |帐号:12

4) ID:21 |电话:900-893-4563 |电子邮件:jdoe@email.com |帐号:23

5) 编号:17 |电话:222-333-1111 |电子邮件:abet@email.com |帐号:3

6) 编号:19 |电话:222-333-1111 |电子邮件:abet@email.com |帐号:3

结果行如下:

1)ID:12、14 |帐号:2、5

2)ID:15、21 |帐号:12、23

不包括条目 #5 和 #6,因为帐户值没有不同,尽管电话和电子邮件相同。

提前致谢!

【问题讨论】:

  • 在您的第一个示例中,您说 ID 为 12 和 14 的记录应在结果集中显示为一行。您如何决定显示两者中的哪一个?更高/更低的ID?更高/更低的帐号?
  • @nb1987 - 抱歉,我早该考虑在问题中添加该细节。在这种情况下,适合在同一列中使用逗号分隔 ID 的单行。
  • 感谢您提供更多详细信息。还有一个问题/澄清 - 是帐户不同但电话或电子邮件相同的包含标准,还是帐户不同但电话和电子邮件相同的包含标准?例如,我注意到您的示例中电话号码相同,但电子邮件不同。
  • 电话或电子邮件应该相同或两者都相同,因此在这种情况下 OR 是合适的。

标签: mysql sql duplicates


【解决方案1】:

您可以使用 group by 和 group concat 来收集所有 id 和 accountno 值。要通过电子邮件或电话号码删除重复项,请使用计数不同。通过 Union all 合并所有结果。 Union 比 union 好,因为我们确信会删除重复项。

演示:http://sqlfiddle.com/#!9/e0af39/2

Select group_concat(id order by id) as id,
group_concat(accountNo order by accountNo) as
accountno
From Tbl
Group by Email
Having count(distinct accountno) > 1
UNION ALL
Select group_concat(id order by id) as id,
group_concat(accountNo order by accountNo) as
 accountno
 From Tbl
 Group by Phone
 Having count(distinct accountno) > 1


Result:
 id accountno
13,17   4,8
12,14   2,5

【讨论】:

  • 感谢您的回复,但在我的情况下不起作用。为了更清楚,我在我的问题中添加了更多细节。
  • 感谢您更新更多示例数据。我更新了我的答案。
  • 感谢您的回答,我终于让您的回答为我的用例工作了!
【解决方案2】:

我创建了一个适用于您的情况的 SQL Fiddle:

http://sqlfiddle.com/#!9/6b77b1/2

查询如下:

SELECT group_concat(t.id order by t.id) as ids
, group_concat(t.accountNo order by t.accountNo) as accounts
FROM tbl t 
JOIN tbl t2 
    ON t2.accountno != t.accountno 
    AND t2.Phone = t.Phone 

UNION 

SELECT group_concat(t.id order by t.id) as ids
, group_concat(t.accountNo order by t.accountNo) as accounts
FROM tbl t 
JOIN tbl t2 
    ON t2.accountno != t.accountno 
    AND t2.Email = t.Email 

基本上,该表会根据您所需的条件(不相等的帐户和相等的电话或不相等的帐户和相等的电子邮件)对自己执行 JOIN,然后使用聚合函数(MySQL 的 GROUP_CONCACT())将匹配的记录放在同一行。

另外,感谢用户 âńōŋŷXmoůŜ,因为我为他的 SQL Fiddle 捎带了架构。

【讨论】:

  • 不客气。我也赞成你的回答。还要注意 SO 在 mySql 中,所以如果可能的话最好使用它。 Group_concat 在我尝试时在 mysql 中运行良好。
  • 感谢您的支持;由于您的回答也很好,因此我依次给出了一个。我看到GROUP_CONCAT 确实有效;当我最初尝试它时,我一定有其他一些语法错误,但奇怪的是 SQL Fiddle 仍然报告 GROUP_CONCAT 不存在。我已经相应地更新了我的答案。
  • 这是 sqlfiddle 在编辑过程中的一个错误。大多数时候,我会重新输入相同的代码或删除/添加任何空格,然后再次运行。
【解决方案3】:

试试这个:

-- records with identical phone but different account
select 
group_concat( id order by id separator ',') id,
group_concat( account order by id separator ',') account
from
test 
where
phone in 
(select phone 
from test
group by phone  having count(distinct account) > 1)  
group by phone
union
-- records with identical email but different account
select 
group_concat( id order by id separator ',') id,
group_concat( account order by id separator ',') account
from
test 
where
email in 
(select email 
from test
group by email  having count(distinct account) > 1)  
group by email

【讨论】:

  • 您可以通过在查询之外添加“有计数”来进一步简化您的答案。
猜你喜欢
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-22
  • 1970-01-01
  • 2011-08-21
  • 1970-01-01
相关资源
最近更新 更多