2017-09-27 8 views
1

2つの列に基づいてグループに日付を再編成したいと思います。以下のデータは、私のデータがどのように見えるかを示しています。私はここに新しいので、あなたに素敵な写真を投稿することはできませんが、履歴書は十分に明確でなければなりません。TSQL - カテゴリの2つのグループに参加する

+-----+-----+--------+ 
| X1 | X2 | Result | 
+-----+-----+--------+ 
| 4 | 1 | A  | 
| 4 | 2 | A  | 
| 1 | 3 | B  | 
| 2 | 3 | B  | 
| 3 | 4 | C  | 
| 3 | 5 | C  | 
| 1 | 6 | B  | 
| 2 | 6 | B  | 
+-----+-----+--------+ 

私のデータが属するカテゴリを示す2つの列があります。私はグループにグループ分けしてグループ化したいと思います。私はこのための効率的なクエリを検索したいと思います。私は最初の要素で始まる再帰クエリを構築できるものと

SELECT * FROM [Table] T1 
JOIN [Table] T2 ON T1.Gr1 = T2.Gr1 OR T1.Gr2 = T2.Gr2 

:現時点では

、私はこのようなものでこれにリンクされている要素持って参加することについて考えました何らかの形でリンクされている場合は次のグループに別のグループを追加するか、そうでない場合は新しいランクに追加します。多くのデータを使用すると、非常に優雅で効率的ではありません。

誰でも解決策がありますか?

EDIT。私の質問は分かりません。各行には2つのカテゴリ変数X1とX2があります。私は共通のものを共有していないグループのすべての観測を分割したい。例では、グループBは、X1 = 1または2またはX2 = 3または6のすべての観測値を保持します。グループCは、x1 = 3およびx2 = 4または5の観測値を保持します。

+1

これはかなり正直なはずですが、私はあなたが出力したいものを理解していません。そして、あなたはあなたのデータの写真を投稿していないのがいいです、あなたは常にテキストとしてデータを投稿するべきです。 –

+0

最後の列は私が望む結果を示しています。一言で言えば、私は閉じたグループにいるように自分のデータを再編成したい。グループAの観察結果は、グループBまたはCの観察結果と一致しません。 – Quidam

+0

これはあなたにとって理にかなっていると確信しています。しかし、私が座っている場所からは、出力はランダムです。あなたはA、B、Cが必要です。ルールは何ですか?なぜ最初の2つの行がグループであるのかについての明確さはありません。そしてなぜ1,2のセットがグループなのか?ここでルールを説明する必要があります。なぜなら、このデータがあなたが何をしようとしているのかをわからないからです。説明にいくつかの努力をして、答えはあなたをかなり早く見つけるでしょう。 –

答えて

0

私はあなたが達成したいことを理解していると思います。

明確にするために、ある種のポインタが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 

が、これは何をするのか、あなた期待?処理する大きなテーブルがある場合は、これをテストしてください。ストアドプロシージャでこれを実現する方法はほぼ確実ですが、必要に応じてビューに入れることができる単一のクエリが提供されます。

上記のスクリプトの改善が歓迎されました。

+0

それは私が探しているものです。私はそれが私のデータベースではうまくいくかどうかはわかりませんが、私は約500,000の観測を持ち、カテゴリーはテキストと固有の識別子で表されています。私はこれを調べます。ありがとう – Quidam

関連する問題