私はあなたが達成したいことを理解していると思います。
明確にするために、ある種のポインタがX1/X2ペアのリストを通り抜けるので、新しいグループをオンザフライで作成したいと思います。 X1 または X2のいずれかがすでに表示されている場合は、それを既存のグループに追加します。そうでない場合は、新しいグループに追加します。
これは、データベース側の計算では、RDBMSが設計されている通常のセットベースの理論には当てはまりません。たとえば、異なるグループにある前の2つの行と一致する場合、どのグループに項目が入りますか?
これはカーソルで行うことができますが、私はカーソルが嫌いですので、少なくともそこには行かないでしょう。私はwindow functionsでこれを達成する方法があると思います。
これを実現する方法のかなり大まかな例です。上のメモの重複行のように、このロジックのニュアンスが期待通りではない場合があります。これは、入力データに何らかの並べ替え/一意のキーがあり、行を処理し、必要に応じて新しいグループを作成し、重複した一致が見つかった場合は最初のインスタンスと一致するものとみなします。
これは非常によく、大きなテーブルに非常に遅くなることがあります(...ので、ユーザは用心し、すべてのもの):
declare @t table (
i int identity, -- here's our ordered key
X1 int,
X2 int
);
-- Here's our test data (a few extra rows added on for good measure
insert into @t
values (4, 1),(4, 2),(1, 3),(2, 3),(3, 4),(3, 5),(1, 6),
(2, 6),(2, 1),(2, 2),(2, 5),(7, 7),(4, 1),(1, 2),
(9, 9),(9, 1)
; with cte as (
-- keep track of the newest group number (by summing the "new group" flags):
select i, X1, X2, sum(newgrp) over (order by i) newestGroupNo
from (
-- This subquery flags whenever there is a row that doesn't
-- match any previous row, and a new group should be created
select X1, X2, i,
case when
(count(*) over (partition by X1 order by i)) = 1 and -- unique over X1
(count(*) over (partition by X2 order by i)) = 1 -- unique over X2
then 1 -- New group
else 0 -- Existing group
end newgrp
from @t
) b
)
-- Now do the uniqueness check again, but either return the new group no,
-- or the group no of the first group that matches prior to this row
select i, X1, X2,
case when
(count(*) over (partition by X1 order by i)) = 1 and -- unique over X1
(count(*) over (partition by X2 order by i)) = 1 -- unique over X2
then newestGroupNo -- New group, return the group number
else (select top 1 newestGroupNo
from cte
where (cte.X1 = c.X1 or cte.X2 = c.X2) and cte.i <= c.i) -- Existing group
end grp
from cte c order by i
結果:
i X1 X2 grp
1 4 1 1 new group
2 4 2 1 match on X1 where i=1
3 1 3 2 no match
4 2 3 2 match on X2 where i=3
5 3 4 3 no match
6 3 5 3 match on X1 where i=5
7 1 6 2 match on X1 where i=3
8 2 6 2 match on X1 where i=4 (not i=7)
9 2 1 1 match on X2 where i=1 (not i=4 or i=8)
10 2 2 1 match on X2 where i=2 (... etc)
11 2 5 2 match on X1 where i=4
12 7 7 4 no match
13 4 1 1 match on X1 where i=1
14 1 2 1 match on X2 where i=2
15 9 9 5 no match
16 9 1 1 match on X2 where i=1
が、これは何をするのか、あなた期待?処理する大きなテーブルがある場合は、これをテストしてください。ストアドプロシージャでこれを実現する方法はほぼ確実ですが、必要に応じてビューに入れることができる単一のクエリが提供されます。
上記のスクリプトの改善が歓迎されました。
これはかなり正直なはずですが、私はあなたが出力したいものを理解していません。そして、あなたはあなたのデータの写真を投稿していないのがいいです、あなたは常にテキストとしてデータを投稿するべきです。 –
最後の列は私が望む結果を示しています。一言で言えば、私は閉じたグループにいるように自分のデータを再編成したい。グループAの観察結果は、グループBまたはCの観察結果と一致しません。 – Quidam
これはあなたにとって理にかなっていると確信しています。しかし、私が座っている場所からは、出力はランダムです。あなたはA、B、Cが必要です。ルールは何ですか?なぜ最初の2つの行がグループであるのかについての明確さはありません。そしてなぜ1,2のセットがグループなのか?ここでルールを説明する必要があります。なぜなら、このデータがあなたが何をしようとしているのかをわからないからです。説明にいくつかの努力をして、答えはあなたをかなり早く見つけるでしょう。 –