【问题标题】:Nested SQL IN statement for cell with more than 1 value具有超过 1 个值的单元格的嵌套 SQL IN 语句
【发布时间】:2020-06-01 08:14:33
【问题描述】:

我如何编写 SQL 以使其返回给我

tom,ken,jerry

我试过这个 SQL

select name
  from staffDB
 where dept in (select value 
                  from ConfigDB 
                 where key = 'dept')

但它不返回任何值,不,不,我不允许更改数据库设计。

【问题讨论】:

    标签: sql oracle listagg


    【解决方案1】:

    您的数据库设计不是最优的,因为它存储的是 CSV 值。话虽如此,这是使用LISTAGG (11g+) 获得所需输出的一种方法:

    SELECT
        c."Key",
        LISTAGG(s.Name, ',') WITHIN GROUP (ORDER BY s.Dept) Departments
    FROM ConfigDB c
    LEFT JOIN StaffDB s
        ON ',' || c."Value" || ',' LIKE '%,' || s.Dept || '%,'
    GROUP BY
        c."Key";
    

    Demo

    请注意,我们使用此逻辑将 config 表中的部门 CSV 列表与 staff 表中的每个标量值进行比较,例如:

    ,A,B,C, LIKE '%,A,%'
    

    也就是说,我们将逗号标记到部门的 CSV 字符串上,以便我们可以搜索用逗号包围的每个可能的标量部门。

    【讨论】:

      【解决方案2】:

      一种选择是用逗号分隔,然后通过在SELECT .. CONNECT BY level .. 语句中使用LISTAGG() 函数进行组合:

      WITH ConfigDB( key, value ) AS
      (
       SELECT 'dept', 'A,B,C' FROM dual
      ), StaffDB( name, dept ) AS
      (
       SELECT 'tom'  , 'A' FROM dual UNION ALL
       SELECT 'ken'  , 'B' FROM dual UNION ALL
       SELECT 'jerry', 'C' FROM dual  
      ), t AS
      (
       SELECT REGEXP_SUBSTR(value,'[^,]',1,level) AS letter, level AS lvl
         FROM ConfigDB
        CONNECT BY level <= REGEXP_COUNT(value,',') + 1
      )
      SELECT LISTAGG(name,',') WITHIN GROUP (ORDER BY lvl) AS DBNAme
        FROM t  
        JOIN StaffDB
          ON dept = letter
      

      Demo

      【讨论】:

        【解决方案3】:

        您可以使用层次查询来拆分值,然后将其连接起来,如下所示:

        SQL>  SELECT
        2      C.KEY,
        3      LISTAGG(S.NAME, ',') WITHIN GROUP(ORDER BY S.DEPT) DEPARTMENTS
        4     FROM
        5      CONFIGDB   C
        6      CROSS JOIN TABLE ( CAST(MULTISET(
        7          SELECT REGEXP_SUBSTR(C.VALUE, '[^,]+', 1, LEVEL)
        8            FROM DUAL
        9          CONNECT BY LEVEL <= REGEXP_COUNT(C.VALUE, '[^,]+')
        10      ) AS SYS.ODCIVARCHAR2LIST) ) C1
        11      LEFT JOIN STAFFDB    S ON S.DEPT = C1.COLUMN_VALUE
        12    GROUP BY C.KEY;
        
        KEY   DEPARTMENTS
        ----- ---------------
        dept  tom,ken,jerry
        
        SQL>
        

        【讨论】:

          【解决方案4】:

          请使用以下查询,

          select * from 
          (select LISTAGG(Name, ',') WITHIN GROUP (ORDER BY Dept) as name, 
          LISTAGG(Dept, ',') WITHIN GROUP (ORDER BY Dept) as dept from staffDB)
          where dept  in
          (select value from ConfigDB);
          

          下面是测试用例,

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-02-15
            • 2013-09-10
            • 2019-12-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-02-11
            • 1970-01-01
            相关资源
            最近更新 更多