从表WHERE的第一行col1 =另一行的col2中选择所有行?

时间:2018-06-19 18:16:40

标签: sql sql-server

考虑表格的子部分:

recId|Col1   |Val1  |Col2   |Val2
________________________________________
    1|'Id'   |'1'   |NULL   |NULL  |
    2|'EmpId'|'100' |'Id'   |'1'   |
    3|'EmpId'|'101' |'Id'   |'1'   |
    4|'KeyId'|'1110'|'EmpId'|'100' |
    5|'EmpId'|'101' |'KeyId'|'1111'|
    6|'Id'   |'2'   |NULL   |NULL  |

我想知道是否有办法从该表中拉出与第一行相关的所有记录,其中id = @id?

在此示例中,让@id = 1。

输出应包含行,其中上面示例表中的recId IN(1,2,3,4,5)(Id = 1由EmpId = 101的行共享,由IDId的行共享) = 1111,等等。

这可能吗?

编辑:

感谢a comment suggestion,我研究了递归公用表表达式。

这是我当前的db<>fiddle

DECLARE @id integer = 1;

;WITH cte
AS  (
    SELECT n=1,recid,col1,val1,col2,val2 from elbat
        WHERE col1 = 'Id' AND val1 = CAST(@id AS varchar(10))
    UNION ALL
        SELECT n=n+1,r.recid,r.col1,r.val1,r.col2,r.val2
        FROM cte p
    INNER JOIN elbat r
        ON r.col1 = p.col1
            AND r.val1 = p.val1
        OR r.col1 = p.col2
            AND r.val1 = p.val2
        OR r.col2 = p.col1
            AND r.val2 = p.val1
        OR r.col2 = p.col2
            AND r.val2 = p.val2
        WHERE r.recid <> p.recid AND p.n = n AND n<3
    )
SELECT recid,col1,val1,col2,val2
FROM   cte
ORDER BY recid;

结果为:

recid   col1    val1    col2    val2
________________________________________
1       Id      1       null    null
1       Id      1       null    null
1       Id      1       null    null
2       EmpId   222     Id      1
2       EmpId   222     Id      1
3       EmpId   223     Id      1
3       EmpId   223     Id      1
4       KeyId   4445    EmpId   222
5       EmpId   223     KeyId   4444

我不确定如何防止无限递归-我需要从当前迭代中排除早期迭代的结果。现在,“ n”限制了深度(通过数量的连接数量),但是如您所见,它在每次迭代中都重复使用了cte中的所有 all 行。

请协助我解决这个问题。谢谢。

1 个答案:

答案 0 :(得分:0)

首先,您需要钥匙

SELECT Col1, Val1
FROM Yourtable t1
WHERE Col1 = 'Id'
  AND Val1 = @id

现在获取与该键匹配的所有行

SELECT *
FROM Yourtable t1
JOIN  ( SELECT Col1, Val1
        FROM Yourtable 
        WHERE col1 = 'Id'
          AND Val1 = @id ) t2
 ON t1.Col2 = t2.Col1
AND t1.Val2 = t2.Val1

使用递归CTE: SQL DEMO

DECLARE @id integer = 1;

;WITH cte AS    (
    SELECT n=1, recid, col1, val1, col2, val2 
    FROM elbat
    WHERE col1 = 'Id' AND val1 = CAST(@id AS varchar(10))

    UNION ALL

    SELECT n=n+1, r.recid, r.col1, r.val1, r.col2, r.val2
    FROM cte p
    JOIN elbat r
      ON r.col2 = p.col1 AND r.val2 = p.val1
)
SELECT n, recid,col1,val1,col2,val2
FROM   cte
ORDER BY recid;