繁体   English   中英

通过T-SQL找到基于传递性的所有可能的对

[英]Find all possible pairs based on transitivity via T-SQL

我有一个问题,不让我已经好几天了。 集体思想是我可以依赖的最后手段。

假设我们有一个包含两列的表。 实际上,值是GUID,但为了简单起见,我们将它们作为字母。

| a | b |
|---|---|
| x | y |
| y | x |
| y | z |
| z | y |
| m | n |
| m | z |

我需要创建一个T-SQL查询,它将从trasitivity中显示所有可能的对,即如果x = y,y = z,则x = z。 此外,必须存在simmetry,即如果有x = y,那么也应该有y = x。 在这种特殊情况下,我认为存在“满屋”,这意味着每个字母都通过中间体与所有其他字母相连。 但我需要一个可以显示的查询。 我所做的只是在这里(SQLFiddle无法运行它):

    WITH
    t AS
      (SELECT 'x' AS a, 'y' AS b
       UNION ALL
       SELECT 'y' AS a, 'x' AS b
       UNION ALL 
       SELECT 'y' AS a, 'z' AS b
       UNION ALL 
       SELECT 'z' AS a, 'y' AS b
       UNION ALL 
       SELECT 'm' AS a, 'n' AS b
       UNION ALL 
       SELECT 'm' AS a, 'z' AS b),

    coupled_reflective AS --for reflective couples we take either of them

      (SELECT t2.a, t2.b
       FROM t t1
       JOIN t t2 ON t1.a=t2.b
       AND t1.b!=t2.a),

    reversive_coupled_reflective AS --that's another half of the above couples (reversed)

      (SELECT t2.b, t2.a
       FROM t t1
       JOIN t t2 ON t1.a=t2.b
       AND t1.b!=t2.a),

    rs AS -- reduce the initial set (t)

      (SELECT *
       FROM coupled_reflective
       UNION
       SELECT *
       FROM t
       EXCEPT
       SELECT *
       FROM reversive_coupled_reflective),

     cte AS -- recursively iterate through the set to find transitive values (get linked by the left field)

      (SELECT a, b
       FROM rs
       UNION ALL
       SELECT rs.b, cte.b
       FROM rs
       JOIN cte ON rs.a=cte.a
       AND rs.b!=cte.b),

     cte2 AS -- recursively iterate through the set to find transitive values (get linked by the right field)

      (SELECT a, b
       FROM rs
       UNION ALL
       SELECT rs.a, cte.a
       FROM rs
       JOIN cte ON rs.b=cte.b
       AND rs.a!=cte.a)



    SELECT a, b FROM cte2
    UNION
    SELECT a, b FROM cte
    UNION
    SELECT a, b FROM t
    UNION
    SELECT b, a FROM t

但不幸的是,这并没有成功。

期望的结果应该是

 | a | b |
 |---|---|
 | x | y |
 | y | x |
 | y | z |
 | z | y |
 | m | n |
 | m | z |
 | n | m |
 | z | m |
 | x | z |
 | z | x |
 | x | m |
 | m | x |
 | x | n |
 | n | x |
 | y | m |
 | m | y |
 | y | n |
 | n | y |

那里有一个有天赋的SQL好友可以帮助我吗?拜托? 谢谢。

您可以使用递归CTE,但需要已访问过的节点列表。 您可以使用字符串实现它:

with cte as (
      select a, b, cast('{' + a + '}{' + b + '}' as varchar(max)) as visited
      from t
      union all
      select cte.a, t.b,
             (visited + '{' + t.b + '}')
      from cte join
           t
           on cte.b = t.a
      where cte.visited not like '%{' + t.b + '}%'
     )
select distinct a, b
from cte;

注意:

以上是图中的有链接。 如果您想要无向链接,请同时包括:

with t as (
      select a, b from yourtable
      union
      select b, a from yourtable
     ),

其余的逻辑遵循使用t

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM