6

関連レコードのグループ内からの重複値を含むすべての個々の行 (グループ化されていない) を返す 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

目的の SQL クエリから返される理想的な出力:

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 は、そのアカウントのレコード グループ内にある他の 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');
4

2 に答える 2

10

このタイプのクエリは、半結合として実装できます。

半結合は、結合内のテーブルの1つから行を選択するために使用されます。

例えば:

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質問の2番目の部分では、クエリの句を更新する必要があります。

于 2012-05-03T13:53:50.523 に答える
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

http://sqlfiddle.com/#!2/a50e9/3

于 2012-05-03T14:07:53.533 に答える