1

いずれかの列から関連するすべてのエイリアス ID を返すクエリが必要です。ここに示されているのは、他の何千もの行の中からいくつかのエイリアスの顧客 ID です。クエリへの入力パラメータが id=7 の場合、5 行 (1,5,7,10,22) を返すクエリが必要です。これは、それらがすべて互いの別名であるためです。たとえば、22 と 10 は 7 の間接エイリアスです。

CustomerAlias
--------------------------
AliasCuID   AliasCuID2 
--------------------------
1           5      
1           7      
5           7      
10          5      
22          1      

以下は顧客テーブルからの抜粋です。

Customer
----------------------------------
CuID    CuFirstName    CuLastName
----------------------------------
 1      Mike           Jones
 2      Fred           Smith
 3      Jack           Jackson
 4      Emily          Simpson
 5      Mike           Jones
 6      Beth           Smith
 7      Mike           jones
 8      Jason          Robard
 9      Emilie         Jiklonmie
 10     Michael        jones
 11     Mark           Lansby
 12     Scotty         Slash
 13     Emilie         Jiklonmy
 22     mike           jones

近づくことはできましたが、間接的に関連するエイリアスを正しく選択できないようです。このクエリを考えると:

SELECT DISTINCT Customer.CuID, Customer.CuFirstName, Customer.CuLastName
FROM  Customer  WHERE  
 (Customer.CuID = 7) OR (Customer.CuID IN
  (SELECT AliasCuID2
    FROM CustomerAlias AS CustomerAlias_2
    WHERE (AliasCuID = 7))) OR (Customer.CuID IN
  (SELECT AliasCuID
  FROM  CustomerAlias AS CustomerAlias_1
  WHERE (AliasCuID2 = 7)))

もちろん、目的の ID の 5 つのうち 3 つを返します。これにより、間接的に関連付けられた 10 と 22 のエイリアス ID が結果行にありません。

1   Mike    Jones
5   Mike    Jones
7   Mike    jones

*以下の提案に基づいて、CTE 階層クエリを試しています。

いくつかの提案に従った後、私は今これを持っています。テーブル内のレコードが十分な即時 ID を参照している限り、これは機能します。ただし、クエリで id=10 を使用すると、データの性質上、まだ不十分です。

DECLARE @id INT
SET @id = 10;

 DECLARE @tmp TABLE ( a1 INT, a2 INT, Lev INT );

WITH Results (AliasCuID, AliasCuID2, [Level]) AS (
   SELECT AliasCuID,
          AliasCuID2,
          0 as [Level]
     FROM CustomerAlias
    WHERE AliasCuID = @id OR AliasCuID2 = @id
   UNION ALL
   -- Recursive step
   SELECT a.AliasCuID,
          a.AliasCuID2,
          r.[Level] + 1 AS [Level]
     FROM CustomerAlias a
     INNER JOIN Results r ON a.AliasCuID = r.AliasCuID2 )

    INSERT INTO @tmp
        SELECT * FROM Results;


WITH Results3 (AliasCuID, AliasCuID2, [Level]) AS (
   SELECT AliasCuID,
          AliasCuID2,
          0 as [Level]
     FROM CustomerAlias
    WHERE AliasCuID = @id OR AliasCuID2 = @id
   UNION ALL
   -- Recursive step
   SELECT a.AliasCuID,
          a.AliasCuID2,
          r.[Level] + 1 AS [Level]
     FROM CustomerAlias a
     INNER JOIN Results3 r ON a.AliasCuID2 = r.AliasCuID )

    INSERT INTO @tmp
        SELECT * FROM Results3;


  SELECT DISTINCT a1 AS id FROM @tmp
  UNION ALL
  SELECT DISTINCT a2 AS id FROM @tmp
  ORDER BY id

これは、関連する ID のリストを提供する単純化されたクエリであることに注意してください。

---
id
---
5
5
7
10

ただし、ID 1 と 22 を取得することはまだできません。

4

2 に答える 2

0

これは、検索の深さ ( https://stackoverflow.com/a/7569520/1803682 ) を把握していない限り、解決するのが簡単な問題ではありません。それ。

深さがわからない場合は、ストアド プロシージャを作成する必要があります。私はほぼ同じ問題に対してこのアプローチに従いました:

UPDATE エイリアスがどのように作成されたかのチェーンを気にしない場合-スクリプトを再帰的に実行して、それらすべてが単一の(マスター?)レコードを参照するようにします。その後、簡単に検索を実行でき、迅速に検索できます。ただし、エイリアスがどのようにトラバースされるかを気にする場合は解決策ではありません。

于 2013-09-03T21:54:17.913 に答える
0

SQL Server 2012 用のSQL Fiddleを作成しました。アクセスできるかできないか教えてください。

ここでの私の考えは、左右のブランチを個別に再帰的にチェックし続けたいということでした。このロジックは、関係が左右の間で跳ね返る場合、おそらく崩壊します。最初の 2 つを参照するように 3 つ目の CTE を設定できますが、左から右、右から左に結合することはできますが、そのための時間はありません。

コードも下にあります。

CREATE TABLE CustomerAlias
(
  AliasCuID INT,
  AliasCuID2 INT
)
GO

INSERT INTO CustomerAlias
SELECT 1,5
UNION SELECT 1, 7
UNION SELECT 5, 7
UNION SELECT 10, 5
UNION SELECT 22, 1
GO

DECLARE @Value INT
SET @Value = 7


; WITH LeftAlias AS
(
  SELECT AliasCuID
    , AliasCuID2
  FROM CustomerAlias
  WHERE AliasCuID2 = @Value

    UNION ALL

  SELECT a.AliasCuID
    , a.AliasCuID2
  FROM CustomerAlias a
  JOIN LeftAlias b
    ON a.AliasCuID = b.AliasCuID2
)
, RightAlias AS
(
  SELECT AliasCuID
    , AliasCuID2
  FROM CustomerAlias
  WHERE AliasCuID = @Value

    UNION ALL

  SELECT a.AliasCuID
    , a.AliasCuID2
  FROM CustomerAlias a
  JOIN LeftAlias b
    ON a.AliasCuID2 = b.AliasCuID
)
SELECT DISTINCT A
FROM
(
  SELECT A = AliasCuID
  FROM LeftAlias

  UNION ALL

  SELECT A = AliasCuID2
  FROM LeftAlias

  UNION ALL

  SELECT A = AliasCuID
  FROM RightAlias

  UNION ALL

  SELECT A = AliasCuID2
  FROM RightAlias
) s
ORDER BY A
于 2013-09-05T21:05:28.367 に答える