3

よくわからない問題に取り組んできました。クロス結合、CTE、ウィンドウ関数などのさまざまな組み合わせを試しましたが、うまくいきませんでした。また、動的SQLルートを使用したくありません。誰か助けてもらえますか?

グループ化された値の変数セットが与えられると、すべての可能な組み合わせが垂直方向に生成されます(派生グループ、値)

追加情報:

  1. 2つの組み合わせは、順序に関係なく、同じ値のセットを持つべきではありません。例:すでに(1,2)がある場合は、(2,1)を生成しないでください。(1,2,3)の場合は、(1,3,2)、(2,1,3)、(2 、3,1)、(3,1,2)、(3,2,1)
  2. 同じグループの値を組み合わせてはいけません
  3. グループに関係なく、すべての値は一意です。最初のグループ化の唯一の理由は、ルール#2を適用することです。

例:開始グループとの値が与えられた

InputGroup値

  • 1 8
  • 2 7
  • 2 9
  • 3 1
  • 3 6
  • 3 3

この出力を生成します

OutputGroup値

  • 1 8
  • 2 7
  • 3 9
  • 4 1
  • 5 6
  • 6 3
  • 7 8
  • 7 7
  • 8 8
  • 8 9
  • 9 8
  • 9 1
  • 10 8
  • 10 6
  • 11 8
  • 11 3
  • 12 7
  • 121
  • 13 7
  • 13 6
  • 14 7
  • 14 3
  • 15 9
  • 151
  • 16 9
  • 16 6
  • 17 9
  • 17 3
  • 18 8
  • 18 7
  • 18 1
  • 19 8
  • 19 7
  • 19 6
  • 20 8
  • 20 7
  • 20 3
  • 21 8
  • 21 9
  • 21 1
  • 22 8
  • 22 9
  • 22 6
  • 23 8
  • 23 9
  • 23 3

これが、出力を生成するための手動の非垂直方式です。

CREATE TABLE #temp1 (GroupID INT, MyValue INT)

INSERT INTO #temp1 (GroupID, MyValue)
VALUES  (1,8),(2,7),(2,9),(3,1),(3,6),(3,3)

--1st set of possibilities
SELECT MyValue
FROM #temp1

--2nd set of possibilities
SELECT a.MyValue, b.MyValue
FROM #temp1 a
JOIN #temp1 b
ON a.GroupID < b.GroupID

--3rd set
SELECT a.MyValue, b.MyValue, c.MyValue
FROM #temp1 a
JOIN #temp1 b
ON a.GroupID < b.GroupID
JOIN #temp1 c
ON b.GroupID < c.GroupID

DROP TABLE #temp1 

私の問題は、開始値の数が可変である可能性があることです。これを念頭に置いて、出力はグループ化された垂直セットである必要があるため、2列のみを返します。1は、番号と番号自体をグループ化します。この特定の例では、上記のように23の異なるグループを持つ46の行が必要です。

私は変更を続け、最終的に廃棄したCTEを作成しました。

WITH    MyCTE
          AS (SELECT    1 AS Level, DENSE_RANK() OVER (ORDER BY GroupID, MyValue) AS DgroupID, GroupID, MyValue
              FROM      #temp1
              UNION ALL
              SELECT    a.Level + 1, DENSE_RANK() OVER (ORDER BY b.GroupID, b.MyValue), b.GroupID, b.MyValue
              FROM      MyCTE a
              JOIN      #temp1 b
                        ON a.GroupID < b.GroupID)

SELECT  DENSE_RANK() OVER (ORDER BY Level, DgroupID), MyValue
FROM    MyCTE 

これに関する明らかな問題:

1)各行に増分値を与えるために使用したウィンドウ関数が期待どおりに機能しませんでした。これはおそらく、CTEの動作方法が原因です。パフォーマンスには良いが、私には悪い。ROW_NUMBERウィンドウ関数は同じことを行います。私がやろうとしているのは、各反復内で行を自動インクリメントして、テーブルが「ピボット解除」されたときにグループを識別できるようにすることだけです。CTEが非常に高速である理由は、実際にはセットベースの操作であるため、再帰があったとしても、意図した結果を生成するためにループ/反復モードの考え方に頼ることができないためだと思います。私のすべての仮定で私を修正してください

2)ピボットを解除します。行のセットを取得し、列を行にピボット解除する必要があります。各行は元の行の識別子を保持して、グループ化されていることを示します。SQL Serverには、UNPIVOTと呼ばれるすばらしいコマンドがあります。これは、設計時にピボットを解除する列の数を知る必要があるため、まったく役に立ちません。これの要点は、可変数の入力を提供し、予測可能な出力を生成できるようにすることです。

4

1 に答える 1

0

したがって、すべての「グループ 1」の値をすべての「グループ 2」の値とすべての「グループ 3」の値でグループ化しようとしていますが、ex: 1,2 と 2,1 について述べたように重複を防ぎます。手動のアプローチは問題ないように見えますが、「値」が以前のものよりも小さいのではなく、グループを比較している理由がわかりません..

SELECT a.MyValue, b.MyValue
FROM #temp1 a
JOIN #temp1 b
ON a.MyValue < b.MyValue AND a.GroupID <> b.GroupID

--3rd set
SELECT a.MyValue, b.MyValue, c.MyValue
FROM #temp1 a
JOIN #temp1 b
ON a.MyValue < b.MyValue AND a.GroupID <> b.GroupID 
JOIN #temp1 c
ON b.MyValue < c.MyValue AND a.GroupID <> c.GroupID AND b.GroupID <> c.GroupID

あなたのフィードバックによると、上記の調整は機能するはずです。番号 1 はグループ 2 に存在する可能性があるため、グループ 1、グループ 2、およびグループ 2、グループ 1 に浸透する必要があるため、余分な筋肉が必要になるだけです。 5 という低い数値です。常に a.Group を b.Group より小さく修飾している場合、グループ 2 がグループ 1 よりも大きいため、最初の位置に値 1 が表示されることはありません。

それはあなたのシナリオにとって意味がありますか?

于 2012-10-22T18:44:51.083 に答える