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)))

当然返回 5 个所需 id 中的 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)——看起来你不知道——并采取蛮力的方法它。

假设您不知道编写存储过程所需的深度。我按照这种方法解决了一个几乎相同的问题:https ://dba.stackexchange.com/questions/7147/find-highest-level-of-a-hierarchical-field-with-vs-without-ctes/7161#7161

更新 如果您不关心如何创建别名的链 - 我会递归运行一个脚本以使它们都引用单个(主?)记录。然后,您可以轻松地进行搜索,它会很快 - 如果您关心别名的遍历方式,这不是一个解决方案。

于 2013-09-03T21:54:17.913 回答
0

我为 SQL Server 2012 创建了一个SQL Fiddle。请让我知道您是否可以访问它。

我的想法是,您只想分别递归地检查左右分支。如果左右之间的关系反弹,这个逻辑可能会崩溃。您可以设置第三个 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 回答