【问题标题】:Recursive query in SQL ServerSQL Server 中的递归查询
【发布时间】:2019-03-20 03:36:52
【问题描述】:

我有一个结构如下的表

表名:matches

这基本上存储了哪个产品与哪个产品匹配。我需要处理这张表 并存储在下面的组表中。

表名:groups

group_ID 存储构成组的Product_IDSMIN Product_ID。举个例子吧

如果 A 匹配 B 并且 B 匹配 C 那么三行应该以(A, A), (A, B), (A, C)格式进入组表

我曾尝试研究相关的子查询和 CTE,但没有实现。

我需要在 SQL 中完成这一切。

感谢您的帮助。

【问题讨论】:

  • 您可以使用recursive CTE
  • 递归 CTE 似乎是在 SQL 中实现递归处理的唯一方法,但我并没有真正解决我的问题。你能举出任何接近我要求的例子吗?感谢您的帮助。
  • 不是真的,我只是浏览所有产品,执行匹配算法,然后将匹配结果保存在“匹配”表中。我认为没有像根节点这样的东西。

标签: sql sql-server


【解决方案1】:

试试这个:

;WITH CTE
AS
(
    SELECT DISTINCT
        M1.Product_ID Group_ID,
        M1.Product_ID
    FROM matches M1
        LEFT JOIN matches M2
            ON M1.Product_Id = M2.matching_Product_Id
    WHERE M2.matching_Product_Id IS NULL
    UNION ALL
    SELECT
        C.Group_ID,
        M.matching_Product_Id
    FROM CTE C
        JOIN matches M
            ON C.Product_ID = M.Product_ID
)
SELECT * FROM CTE ORDER BY Group_ID

您可以使用OPTION(MAXRECURSION n) 来控制递归深度。

SQL FIDDLE DEMO

【讨论】:

  • 当我尝试使用我的实际数据时,这不会返回任何结果。 http://sqlfiddle.com/#!3/aff16/1
  • @Ankit 我认为你应该避免像 (1, 2) 和 (2, 1) 这样的一对。
  • 谢谢我照你说的做,看这里sqlfiddle.com/#!3/d41d8/8042 查询这个数据工作正常。但是将 (2294543, 1802989) 添加到最后会破坏它并开始给出最大递归级别达到错误。知道这是为什么吗?什么样的数据会导致这种情况?
  • 好的,如果你添加 (2294543, 1802989) 你会得到这个对 (1802989, 2294543) 的无限递归。请参阅我上面的评论。
  • 好的,我知道出了什么问题。如果数据像 A 匹配 B 和 C 并且 C 匹配 D 那么它可以工作并组成组 (A, B, C, D) 但如果数据像 A 匹配 B 和 C 并且 D 匹配 C 那么它组成两个组 (ABC) (直流)。似乎它只适用于一种方式,而不是两种方式。
【解决方案2】:

类似的东西(未测试)

with match_groups as (

  select product_id, 
         matching_product_id,
         product_id as group_id
  from matches
  where product_id not in (select matching_product_id from matches)

  union all

  select m.product_id, m.matching_product_id, p.group_id
  from matches m
    join match_groups p on m.product_id = p.matching_product_id
)
select group_id, product_id
from match_groups
order by group_id;

【讨论】:

【解决方案3】:

递归级别的示例:

DECLARE @VALUE_CODE AS VARCHAR(5);

--SET @VALUE_CODE = 'A' -- Specify a level

WITH ViewValue AS
(
    SELECT ValueCode
    , ValueDesc
    , PrecedingValueCode
    FROM ValuesTable
    WHERE PrecedingValueCode IS NULL
    UNION ALL
    SELECT A.ValueCode
    , A.ValueDesc
    , A.PrecedingValueCode 
    FROM ValuesTable A
    INNER JOIN ViewValue V ON
        V.ValueCode = A.PrecedingValueCode
)

SELECT ValueCode, ValueDesc, PrecedingValueCode

FROM ViewValue

--WHERE PrecedingValueCode  = @VALUE_CODE -- Specific level

--WHERE PrecedingValueCode  IS NULL -- Root

【讨论】:

  • 如果@VALUE_CODE 的每个实例都在之后被注释掉,为什么还要声明它?此外,这个答案似乎非常特定于您的表格格式,而不是问题中引用的架构
猜你喜欢
  • 2014-12-19
  • 2012-12-05
  • 1970-01-01
  • 1970-01-01
  • 2014-10-10
  • 2011-02-21
  • 1970-01-01
  • 2013-01-10
相关资源
最近更新 更多