【问题标题】:Return true/false in recursive SQL query based on condition在基于条件的递归 SQL 查询中返回真/假
【发布时间】:2021-11-01 02:23:01
【问题描述】:

我有以下流程图。希望它是不言自明的

在层次结构的顶部有一个请求,它是其下所有请求的基本父级。以下请求具有 'id'、'parent_id'、'state' 字段

我的最终目标是找出至少一个父子请求是否具有非法/不合法状态。有一些“不合法”的状态——这就是我使用NOT IN 的原因。所以,如果至少一个子请求的状态错误,我需要简单地返回真/假

我使用下面的查询来构建层次结构

DECLARE @main_parent_id bigint = 1

; with cte 
    as (select id
        from tbl_request as rH 
        WHERE id = @main_parent_id
        UNION ALL
        select rH.id 
        from tbl_request as rH 
        join cte
        on rH.parent_id = cte.id
       WHERE rH.state NOT IN('not-legit'))
    select *
    from cte
    order by id; 

但我不知道如何返回真/假,而不仅仅是返回 id。此外,@main_parent_id 是一个动态变量,它来自另一个 SELECT,它返回层次结构顶部的所有请求。

从某种意义上说,如果所有子请求都处于LEGIT 状态,则上面的查询应该返回true,如果至少有一个子请求处于NOT-LEGIT 状态,则返回false。

为了您的方便,这里是SQL Fiddle

【问题讨论】:

  • 这听起来像是对IF EXISTS/IF NOT EXISTS 的查询 - 所以如果一条记录存在于非法状态,则选择 0,否则选择 1
  • 您的第一个也是最大的问题是您过滤不合法。您如何与您告诉编译器遗漏的东西进行比较?其次,您可以在 cte 输出的最终选择中轻松处理此问题
  • 感谢您发布代码和 sql 小提琴!不过,您现有的代码似乎与您的意图不太相符。现在,您正在构建一个仅包含“合法”请求的层次结构。但这并不能帮助您确定“父级的至少一个子请求是否不合法”。因此,与其说是关于返回 ID 的问题,不如说是关于如何“解析”整个层次结构的问题。对吗?

标签: sql sql-server common-table-expression hierarchy recursive-query


【解决方案1】:

这里试试这个,我刚刚测试了它,它可以工作

部分问题是您过滤掉了不合法的内容。其次,您可以使用 CASE WHEN 来测试是否存在“不合法”。

; WITH cte as 
    (
        SELECT id, state
        FROM tbl_request AS rH 
        WHERE id = @main_parent_id
        UNION ALL
        SELECT rH.id, rh.state 
        FROM tbl_request AS rH 
        INNER JOIN cte ON rH.parent_id = cte.id
    )
    SELECT
      CASE WHEN SUM
        (
            CASE WHEN state='not-legit' THEN 1 ELSE 0 END
        )>0 THEN 'false' ELSE 'true' END
    FROM cte
  ;

【讨论】:

    【解决方案2】:

    你的意思是这样的?

    DECLARE @main_parent_id bigint = 1
    
    ;with cte as (
      select id, state
      from tbl_request as rH 
      WHERE id = @main_parent_id
      UNION ALL
      select rH.id, rh.state
      from tbl_request as rH 
        join cte
          on rH.parent_id = cte.id
    )
    select
      case when (select top 1 1 from cte where state = 'not-legit') = 1 then 'true' else 'false' end as NonLegit
    

    【讨论】:

      【解决方案3】:

      找到不合法的分支时停止搜索。

      with cte 
          as (select id, state
              from tbl_request as rH 
              WHERE id = @main_parent_id
              UNION ALL
              select rH.id, rH.state
              from tbl_request as rH 
              join cte
                on rH.parent_id = cte.id
                   and (cte.state is null or cte.state NOT IN('not-legit'))
             )
          select case when exists(select 1 from cte where  cte.state IN('not-legit'))
              then 1 else 0 end
      

      【讨论】:

      • 您好,感谢您的回答能否告诉我如何将它与AND 声明一起使用?
      • ... AND 存在(从 cte 中选择 1 where cte.state IN('not-legit')) ..
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-23
      • 1970-01-01
      • 2021-06-01
      • 2021-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多