选择其他两列中具有匹配值的行

时间:2019-03-15 13:21:28

标签: sql tsql

Id   ||   IdFrom  ||  IdTo
--------------------------
1    ||    null   ||  2
2    ||    1      ||  null
3    ||    null   ||  5
4    ||    null   ||  6
5    ||    3      ||  9
6    ||    4      ||  7
7    ||    6      ||  null
8    ||    null   ||  null
9    ||    5      ||  10
10   ||    9      ||  null
947  ||    null   ||  949
949  ||    947    ||  952
950  ||    null   ||  951
951  ||    950    ||  952
952  ||    951    ||  null

在指定给定ID时,需要获取所有行,或者仅获取在所有3列之间找到的ID。因此,一个SELECT(在IdFrom或IdTo中找到的所有ID以及那些IdFrom或IdTo的所有ID在其他IdFrom或IdTo的中)

搜索ID 1时的结果将给出ID 1和2的结果

搜索ID 2时的结果将给出ID 1和2的结果

搜索ID 3、5、9或10时的结果将给出ID 3、5、9和10的结果

搜索ID 4,6或7时的结果将给出ID 4,6和7的结果

我当前的搜索是获取IdFrom和IdTo以获得Id的迭代,将找到的Id放入tmp表中,然后再次迭代搜索匹配项,直到找不到更多不同的Id。它可以工作,但是非常丑陋,并且可能花费更长的时间...

在整个查询中都可以使用,该查询可以获取所有具有匹配但未指定特定ID的行

DECLARE @SearchForId int = 1
SELECT 
    t1.ID,t1.IdFROM,t1.IdTO
FROM SomeTable t1
WHERE
    (
        EXISTS(SELECT Id FROM SomeTable tblFROM WHERE tblFROM.IdFROM = t1.Id) OR
        EXISTS(SELECT Id FROM SomeTable tblTO WHERE IdTO.IDTRANSFEREDTO = t1.Id)
    )  
AND Id = 1 <<-- this part just gives that id obvious but without it, it gets everything in the entire table

编辑:添加了新ID(947-952)。先前选择的解决方案确实提供了编号947和949,但缺少950,951,952。尝试像上一个解决方案一样添加另一对cte,给所有ID 947,949,950,951,952,但仅给出947和949。如何获得所有ID 5.该解决方案的速度快了将近25倍。想要保留并获得剩余ID的

2 个答案:

答案 0 :(得分:1)

您需要使用两个递归common table expressions

declare @id int
set @id = 2  

;WITH CTE1 
    AS(
        SELECT c.*
        FROM tbl c
        WHERE c.Id = @id

        UNION ALL

        SELECT p.*
        FROM CTE1 cte1_alias
        INNER JOIN  tbl p 
          ON p.IdFrom = cte1_alias.Id
    ),
    CTE2
    AS(
        SELECT c.*
        FROM tbl c
        WHERE c.Id = @id

        UNION ALL

        SELECT p.*
        FROM CTE2 cte2_alias
        INNER JOIN  tbl p 
          ON p.IdTo = cte2_alias.Id
    )

SELECT Id FROM CTE1
Union 
SELECT Id FROM CTE2

答案 1 :(得分:0)

据我了解,将列等于给定值就足够了:

Declare @prm int = 1
Select Id
From SomeTable
Where Id=@prm Or IdFrom=@prm Or IdTo=@prm

或换一种口味,在列之间使用

Declare @prm int = 1
Select Id
From SomeTable
Where @prm in (Id, IdFrom, IdTo)