我正在尝试创建一个MySQL查询,该查询将返回包含一组相关记录中的重复值的所有单独行(未分组)。 “相关记录组”是指具有相同帐号的组(根据下面的示例)。
基本上,在共享相同的不同帐号的每组相关记录中,只选择那些date
或amount
列的值与该帐户组中其他行的值相同的行的记录。只应将该值视为该帐户组内的重复值。下面的样本表和理想的输出细节应该可以解决问题。
另外,我不关心任何状态为X的记录,即使它们有重复的值。
id account invoice date amount status
1 1 1 2012-04-01 0 X
2 1 2 2012-04-01 120 P
3 1 2 2012-05-01 120 U
4 1 3 2012-05-01 117 U
5 2 4 2012-04-01 82 X
6 2 4 2012-05-01 82 U
7 2 5 2012-03-01 81 P
8 2 6 2012-05-01 80 U
9 3 7 2012-03-01 80 P
10 3 8 2012-04-01 79 U
11 3 9 2012-04-01 78 U
id account invoice date amount status
2 1 2 2012-04-01 120 P
3 1 2 2012-05-01 120 U
4 1 3 2012-05-01 117 U
6 2 4 2012-05-01 82 U
8 2 6 2012-05-01 80 U
10 3 8 2012-04-01 79 U
11 3 9 2012-04-01 78 U
因此,第7/9行和第8/9行不应同时返回,因为它们的重复值在各自的帐户范围内不被视为重复。但是,应返回第8行,因为它与第6行共享一个重复值。
稍后,我可能希望通过仅抓取具有匹配状态的重复行来进一步磨练选择,因此排除第2行,因为它与该帐户的记录组中找到的其他两个不匹配。进行查询会有多困难?它只是添加WHERE或HAVING子句的问题,还是比它更复杂?
我希望我对我想要完成的事情的解释是有道理的。我尝试过使用INNER JOIN但是多次返回每个所需的行。我不想要重复的重复。
CREATE TABLE payment (
id int(11) NOT NULL auto_increment,
account int(10) NOT NULL default '0',
invoice int(10) NOT NULL default '0',
date date NOT NULL default '0000-00-00',
amount int(10) NOT NULL default '0',
status char(1) NOT NULL default '',
PRIMARY KEY (id)
);
INSERT INTO payment VALUES (1, 1, 1, '2012-04-01', 0, 'X');
INSERT INTO payment VALUES (2, 1, 2, '2012-04-01', 120, 'P');
INSERT INTO payment VALUES (3, 1, 2, '2012-05-01', 120, 'U');
INSERT INTO payment VALUES (4, 1, 3, '2012-05-01', 117, 'U');
INSERT INTO payment VALUES (5, 2, 4, '2012-04-01', 82, 'X');
INSERT INTO payment VALUES (6, 2, 4, '2012-05-01', 82, 'U');
INSERT INTO payment VALUES (7, 2, 5, '2012-03-01', 81, 'p');
INSERT INTO payment VALUES (8, 2, 6, '2012-05-01', 80, 'U');
INSERT INTO payment VALUES (9, 3, 7, '2012-03-01', 80, 'U');
INSERT INTO payment VALUES (10, 3, 8, '2012-04-01', 79, 'U');
INSERT INTO payment VALUES (11, 3, 9, '2012-04-01', 78, 'U');
答案 0 :(得分:10)
此类查询可以实现为semi join。
Semijoins用于从联接中表的一个中选择行。
例如:
select distinct l.*
from payment l
inner join payment r
on
l.id != r.id and l.account = r.account and
(l.date = r.date or l.amount = r.amount)
where l.status != 'X' and r.status != 'X'
order by l.id asc;
请注意使用distinct
,并且我只选择左表中的列。这可以确保没有重复。
连接条件检查:
l.id != r.id
)l.account = r.account
)l.date = r.date or l.amount = r.amount
)对于问题的第二部分,您需要更新查询中的on
子句。
答案 1 :(得分:3)
这似乎有效
select * from payment p1
join payment p2 on
(p1.id != p2.id
and p1.status != 'X'
and p1.account = p2.account
and (p1.amount = p2.amount or p1.date = p2.date))
group by p1.id