【问题标题】:Can this result be achieved with a recursive cte?这个结果可以用递归 cte 来实现吗?
【发布时间】:2016-12-01 00:21:59
【问题描述】:

我目前有一个如下所示的表格:

| A_URN | B_URN | ID |
|-------|-------|----|
| 101   | 901   | 0  |
|-------|-------|----|
| 102   | 901   | 0  |
|-------|-------|----|
| 101   | 902   | 0  |
|-------|-------|----|
| 102   | 902   | 0  |
|-------|-------|----|
| 201   | 902   | 0  |
|-------|-------|----|
| 201   | 903   | 0  |
|-------|-------|----|
| 202   | 903   | 0  |
|-------|-------|----|
| 301   | 904   | 0  |
|-------|-------|----|
| 302   | 904   | 0  |
|-------|-------|----|
| 301   | 905   | 0  |
|-------|-------|----|
| 302   | 905   | 0  |
|-------|-------|----|
| 303   | 905   | 0  |
|-------|-------|----|
| 101   | 906   | 0  |

我需要添加一个标识符,将所有相关项目组合在一起。

例如,A_URN 101 连接到 B_URN 901、902 和 906,并且 B_URN 901、902 和 906 还包含 A_URN 102 和 201

A_URN 201 也连接到 B_URN 903 等等。

最终结果应该类似于:

| A_URN | B_URN | ID |
|-------|-------|----|
| 101   | 901   | 1  |
|-------|-------|----|
| 102   | 901   | 1  |
|-------|-------|----|
| 101   | 902   | 1  |
|-------|-------|----|
| 102   | 902   | 1  |
|-------|-------|----|
| 201   | 902   | 1  |
|-------|-------|----|
| 201   | 903   | 1  |
|-------|-------|----|
| 202   | 903   | 1  |
|-------|-------|----|
| 301   | 904   | 2  |
|-------|-------|----|
| 302   | 904   | 2  |
|-------|-------|----|
| 301   | 905   | 2  |
|-------|-------|----|
| 302   | 905   | 2  |
|-------|-------|----|
| 303   | 905   | 2  |
|-------|-------|----|
| 101   | 906   | 1  |

我编写了一个使用 WHILE() 循环完成此任务的查询,但被要求将其重新编写为递归 CTE。 我已经尝试过,但总是需要在不允许的递归成员中使用 MIN 或 GROUP BY。

是否有可能使用递归查询得到这种结果?

【问题讨论】:

  • 你能用while循环发布解决方案吗?
  • 您使用什么 RDBMS(MSSQL、Oracle)?

标签: sql recursion common-table-expression


【解决方案1】:

如果您需要具有递归 CTE 的 MSSQL 解决方案。这是一个适合您的情况的查询from my answer to the similar question

WITH T as 
(
  SELECT A_URN,B_URN, ROW_NUMBER() OVER (ORDER BY A_URN) as ID FROM Table14
)
,CTE AS 
(
  SELECT CAST(','+CAST(A_URN AS Varchar(100)) +','+ CAST(B_URN as Varchar(100))+',' as Varchar(MAX)) as GroupCont,
        id
  FROM T
  UNION ALL
  SELECT CAST(GroupCont+CAST(A_URN AS Varchar(100)) +','+ CAST(B_URN as Varchar(100))+',' AS Varchar(MAX)) as GroupCont,
         pm.id
  FROM CTE 
  JOIN T as pm
  ON 
     (
       CTE.GroupCont LIKE '%,'+CAST(pm.A_URN AS Varchar(100))+',%'
       OR 
       CTE.GroupCont LIKE '%,'+CAST(pm.B_URN AS Varchar(100))+',%'
     )
     AND NOT  
     (
       CTE.GroupCont LIKE '%,'+CAST(pm.A_URN AS Varchar(100))+',%'
       AND 
       CTE.GroupCont LIKE '%,'+CAST(pm.B_URN AS Varchar(100))+',%'
     )
),
T1 AS 
(
 SELECT pm.A_URN,
       pm.B_URN,  
       ISNULL(
        (SELECT MAX(ID) FROM CTE WHERE 
        (
           CTE.GroupCont LIKE '%,'+CAST(pm.A_URN AS Varchar(100))+',%'
           OR 
           CTE.GroupCont LIKE '%,'+CAST(pm.B_URN AS Varchar(100))+',%'
        ))
        ,pm.ID) as ID
FROM T pm
)

SELECT A_URN,B_URN, 
       DENSE_RANK() OVER (ORDER BY ID) AS ID 
FROM T1
ORDER BY B_URN,A_URN

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-17
    • 1970-01-01
    • 2021-03-15
    • 2021-02-04
    • 2012-11-05
    • 1970-01-01
    相关资源
    最近更新 更多