带案例表达的“非单组分组功能”

时间:2019-08-28 10:16:16

标签: sql oracle case

当我尝试使用case表达式时,出现错误“ ORA-00937:不是单组功能”:

SELECT  CASE 
   WHEN EXTRACT_TABLE IS NOT NULL 
   THEN 
  'SELECT '||LISTAGG((EXTRACT_TABLE||'.'||EXTRACT_COLONNE ||' AS " '|| EXTRACT_LIBELLE || ' " '),',') WITHIN GROUP(ORDER BY EXTRACT_ORDRE)
   ELSE 'SELECT '||LISTAGG((EXTRACT_COLONNE ||' AS " '|| EXTRACT_LIBELLE || ' " '),',') WITHIN GROUP(ORDER BY EXTRACT_ORDRE)
    END

不用大小写表达式就可以正常工作,

SELECT
  'SELECT '||LISTAGG((EXTRACT_TABLE||'.'||EXTRACT_COLONNE ||' AS " '|| EXTRACT_LIBELLE || ' " '),',') WITHIN GROUP(ORDER BY EXTRACT_ORDRE)

但是我真的需要检查EXTRACT_TABLE是否为空。我该如何解决?

谢谢

3 个答案:

答案 0 :(得分:1)

CASE内使用LISTAGG

WITH sample AS (SELECT 1 AS EXTRACT_ORDRE, 'tab1' AS EXTRACT_TABLE, 'col1' AS EXTRACT_COLONNE, 'name1' AS EXTRACT_LIBELLE FROM DUAL
                    UNION ALL
                    SELECT 2, 'tab2', 'col2', 'name2' FROM DUAL
                    UNION ALL
                    SELECT 3, NULL, 'col3', 'name3' FROM DUAL
                    )
    select 'SELECT '||LISTAGG(CASE WHEN EXTRACT_TABLE IS NOT NULL THEN (EXTRACT_TABLE||'.'||EXTRACT_COLONNE ||' AS " '|| EXTRACT_LIBELLE || ' " ') 
                ELSE EXTRACT_COLONNE ||' AS " '|| EXTRACT_LIBELLE || ' " ' END ,',') WITHIN GROUP(ORDER BY EXTRACT_ORDRE) AS result
    from sample;

输出:

RESULT
-------------------
SELECT tab1.col1 AS " name1 " ,tab2.col2 AS " name2 " ,col3 AS " name3 "

答案 1 :(得分:0)

该错误表示您需要在group-by子句中包含extract_table;或添加分组依据(如果您还没有),这可能涉及识别其他列,并可能影响输出。这取决于查询的其余部分和数据以及期望的结果。

您原来的非案例方法会在输出中留下不需要的时间段。例如,对于一些示例数据,使用CTE,您的查询将给出:

-- CTE for sample data
with cte (extract_table, extract_colonne, extract_libelle, extract_ordre) as (
  select null, 'col1', 'label1', 2 from dual
  union all
  select 'tab42', 'col2', 'label2', 3 from dual
  union all
  select 'tab42', 'col3', 'label3', 1 from dual
)
-- actual query
SELECT
  'SELECT '||LISTAGG((EXTRACT_TABLE||'.'||EXTRACT_COLONNE ||' AS " '|| EXTRACT_LIBELLE || ' " '),',') WITHIN GROUP(ORDER BY EXTRACT_ORDRE)
from cte;

SELECT tab42.col3 AS " label3 " ,.col1 AS " label1 " ,tab42.col2 AS " label2 "

您的case-expression方法带有一个附加的group by EXTRACT_TABLE子句,可以将该数据分成两个结果:

-- CTE for sample data
with cte (extract_table, extract_colonne, extract_libelle, extract_ordre) as (
  select null, 'col1', 'label1', 2 from dual
  union all
  select 'tab42', 'col2', 'label2', 3 from dual
  union all
  select 'tab42', 'col3', 'label3', 1 from dual
)
-- actual query
SELECT 
  CASE 
     WHEN EXTRACT_TABLE IS NOT NULL THEN 
      'SELECT '||LISTAGG((EXTRACT_TABLE||'.'||EXTRACT_COLONNE ||' AS " '|| EXTRACT_LIBELLE || ' " '),',') WITHIN GROUP(ORDER BY EXTRACT_ORDRE)
     ELSE 
       'SELECT '||LISTAGG((EXTRACT_COLONNE ||' AS " '|| EXTRACT_LIBELLE || ' " '),',') WITHIN GROUP(ORDER BY EXTRACT_ORDRE)
  END
from cte
group by EXTRACT_TABLE;

SELECT tab42.col3 AS " label3 " ,tab42.col2 AS " label2 " 
SELECT col1 AS " label1 " 

可能不是您想要的。但是,如果您实际上有一个过滤器,并确保所有选定的行都具有或不具有表名-而不是上面的混合表-那么这仍然可以使用。

另一种方法是只跳过表名,或更重要的是跳过将表名和列名分开的.,进一步进入查询;也就是说,将'.'替换为CASE WHEN EXTRACT_TABLE IS NOT NULL THEN '.',有条件地跳过了这段时间。当该列为null时,无论如何将没有名称部分,并且该表达式将取消句点,因此您只能获得该列的名称。

SELECT
  'SELECT ' || LISTAGG((EXTRACT_TABLE
    || CASE WHEN EXTRACT_TABLE IS NOT NULL THEN '.' END
    || EXTRACT_COLONNE || ' AS " ' || EXTRACT_LIBELLE || ' " '), ',')
  WITHIN GROUP(ORDER BY EXTRACT_ORDRE)

使用相同的示例数据获取一行,而没有无效的前置时间:

-- CTE for sample data
with cte (extract_table, extract_colonne, extract_libelle, extract_ordre) as (
  select null, 'col1', 'label1', 2 from dual
  union all
  select 'tab42', 'col2', 'label2', 3 from dual
  union all
  select 'tab42', 'col3', 'label3', 1 from dual
)
-- actual query
SELECT
  'SELECT ' || LISTAGG((EXTRACT_TABLE
    || CASE WHEN EXTRACT_TABLE IS NOT NULL THEN '.' END
    || EXTRACT_COLONNE || ' AS " ' || EXTRACT_LIBELLE || ' " '), ',')
  WITHIN GROUP(ORDER BY EXTRACT_ORDRE)
from cte;

SELECT tab42.col3 AS " label3 " ,col1 AS " label1 " ,tab42.col2 AS " label2 " 

答案 2 :(得分:0)

这是您的查询:

SELECT (CASE WHEN EXTRACT_TABLE IS NOT NULL 
             THEN <expression with LISTAGG()>
             THEN <expression with LISTAGG()>
        END)
FROM t;

由于LISTAGG(),这是一个聚合查询。但是,没有 GROUP BY。在这种情况下,所有列引用必须是聚合函数的参数。

我认为您的意思是其中之一:

SELECT (CASE WHEN EXTRACT_TABLE IS NOT NULL 
             THEN <expression with LISTAGG()>
             THEN <expression with LISTAGG()>
        END)
FROM t
GROUP BY EXTRACT_TABLE;

或者:

SELECT <expression with LISTAGG()>
FROM t
WHERE EXTRACT_TABLE IS NOT NULL
UNION ALL
SELECT <expression with LISTAGG()>
FROM t
WHERE EXTRACT_TABLE IS NULL;

您可能还打算进行条件聚合:

SELECT 'SELECT '|| LISTAGG((EXTRACT_TABLE || '.' || col_lib ||'  AS " '|| EXTRACT_LIBELLE || ' " '), ',') WITHIN GROUP(ORDER BY EXTRACT_ORDRE)
FROM (SELECT (CASE WHEN EXTRACT_TABLE IS NOT NULL 
                   THEN EXTRACT_COLONNE
                   ELSE EXTRACT_LIBELLE
              END) as col_lib
             t.*
      FROM t
     ) t