MySQL查询有效地返回不包括重复信息的组合行
Posted
技术标签:
【中文标题】MySQL查询有效地返回不包括重复信息的组合行【英文标题】:MySQL query to efficiently return combined rows excluding duplicated info 【发布时间】:2020-10-20 03:01:14 【问题描述】:所以这可能很简单,但我正在努力寻找一种有效的方法来做到这一点。我查看了许多其他问答,我已经搞砸了 DISTINCT、GROUP BY、子查询等。
我试图超级简化这个例子。 (出于示例的目的,没有 DB 规范化)这是一个 SQL 小提琴:
http://sqlfiddle.com/#!9/948be7c/1
CREATE TABLE IF NOT EXISTS `orders` (
`id` int NOT NULL,
`name` varchar(90) NULL,
`email` varchar(200) NULL,
`phone` varchar(200) NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `orders` (`id`, `name`, `email`, `phone`) VALUES
('1', 'Bob', 'bob@email.com', NULL),
('2', 'Bobby', 'bob@email.com', '1115551111'),
('3', 'Robert', 'robert@email.com', '1115551111'),
('4', 'Fred', 'fred@email.com', '1115552222'),
('5', 'Freddy', 'fred@email.com', '1115553333')
如果我只是运行一个简单的选择,我会得到:
但我想对具有相同电子邮件地址或具有相同电话号码的任何结果“去重” - 因为他们将是同一个人,即使他们有多个 ID,即使他们他们的名字拼写不同。然后合并这些结果(“不同的”电子邮件地址之一和“不同的”电话号码之一以及姓名之一和 ID 之一。)
因此,对于上述内容,我最终会得到这样的结果:
有什么建议吗?
【问题讨论】:
什么决定了为重复返回哪个 id/name? 一开始为什么会有重复数据?您应该规范化您的数据库,以便所有客户信息都在另一个表的一行中,并且order
表具有customer
表的外键。
我尝试了 DISTINCT 和 GROUP BY 的多种变体,但没有得到我想要的。 (而且我的实际数据库要复杂得多,所以这些查询不相关。)
哪个 ID / 名字真的不重要。只需成为与电子邮件和电话匹配的其中之一即可。
您必须选择一组列作为分组依据。我认为没有任何方法可以按一组可变的列进行分组。
【参考方案1】:
我认为您可以通过使用相关子查询进行过滤来做您想做的事情:
select o.*
from orders o
where o.id = (
select o1.id
from orders o1
where o1.email = o.email or o1.phone = o.phone
order by o1.phone is not null desc, o1.email is not null desc, id
limit 1
)
这仅保留具有相同phone
或email
的行中的一行,同时优先考虑phone
和email
不是null
的行。通过选择最低的id
打破平局。
对于您的示例数据,这将返回:
id name email phone
2 Bobby bob@email.com 1115551111
4 Fred fred@email.com 1115552222
【讨论】:
我需要将它重构到我的场景中 - 但它似乎可以满足我的需要!我在 WHERE 子句中使用了很多它,但我不熟悉在 ORDER BY 中包含 IS NOT NULL 的能力 - 我必须对此进行一些阅读! @BeninCA 是的,order by 可以包含任何表达式,而不仅仅是列。请使用实际数量的记录尝试这种方法,并确保它能够充分满足您的需求【参考方案2】:可以通过多种不同的方式来解释您的需求。
一种方法是将其重新定义为约束:仅在其中一个为真时才返回记录:
它有一个非空的电子邮件和电话,并且不存在具有相同电子邮件和电话且 ID 较低的记录 它有一个非空的email但为空的电话,并且没有相同的电子邮件和一个非空电话的记录,并且没有相同的电子邮件和一个空电话和较低的id的记录 它有一个非空电话但为空电子邮件,并且不存在相同电话和非空电子邮件的记录,并且不存在相同电话和空电子邮件和较低id的记录这很容易转化为几个连接,不需要 group by 或 distinct。
【讨论】:
嗯。我认为您的建议将完成我所需要的。我没有想到“低身份”的概念。 当你说约束时——你的意思是作为 JOIN 上的 ON 语句的一部分还是使用 WHERE?以上是关于MySQL查询有效地返回不包括重复信息的组合行的主要内容,如果未能解决你的问题,请参考以下文章