在聚合函数中获取不是单个组函数的错误

Getting error of not a single group function in aggregated function

CREATE TABLE test1 (
    e_id       NUMBER(1),
    e_ques_id  NUMBER(10)
);

INSERT INTO test1 VALUES(1,3);
INSERT INTO test1 VALUES(1,4);

CREATE TABLE test_ref (
    code     NUMBER(1),
    c_value  VARCHAR2(20)
);

INSERT INTO test_ref VALUES(3,'May');
INSERT INTO test_ref VALUES(4,2022);

COMMIT;

Tool Used: SQL Developer(18c)

有两个 tables test1test_ref 我想从 test_ref table 中获取值以便将月份和年份列值。

预期输出:

+------+------------+
| e_id | month_year |
+------+------------+
|    1 | May 2022   |
+------+------------+

我的尝试:

SELECT t.e_id,
LISTAGG(c_value,' ')month_year
FROM test1 t
JOIN test_ref tr ON(t.e_ques_id = tr.code)
WHERE t.e_ques_id IN(3,4)
GROUP BY t.e_id;

这为我提供了我正在寻找的确切结果,但我需要在现有视图中添加此逻辑,我需要使用聚合或案例表达式来获取结果。因此我尝试使用 CASEMAX 但它给我一个错误,不是单个组函数

我的尝试(导致错误):

SELECT t.e_id,
MAX(CASE
WHEN t.e_ques_id IN(3,4) THEN LISTAGG(c_value,' ')
END )month_year
FROM test1 t
JOIN test_ref tr ON(t.e_ques_id = tr.code)
GROUP BY t.e_id;

对我来说,很难猜测为什么现有视图需要聚合函数或case表达式。

无论如何:如果您在其分析形式中使用 max,请跳过 case 表达式,而是将 e_ques_id 条件移动到 where 子句中(因为您已经在查询中做了 works),你会得到这个:

SQL>   SELECT t.e_id,
  2           MAX (LISTAGG (c_value, ' ') WITHIN GROUP (ORDER BY code))
  3              OVER (ORDER BY NULL) month_year
  4      FROM test1 t JOIN test_ref tr ON t.e_ques_id = tr.code
  5     WHERE t.e_ques_id IN (3, 4)
  6  GROUP BY t.e_id;

      E_ID MONTH_YEAR
---------- ---------------
         1 May 2022

SQL>

我不知道这是否会(或不会)在该视图中起作用,但是 - 您可以尝试一下。

你可以在里面使用条件聚合 LISTAGG:

SELECT t.e_id,
       LISTAGG(CASE WHEN t.e_ques_id IN (3,4) THEN c_value END, ' ')
         WITHIN GROUP (ORDER BY t.e_ques_id) AS month_year
FROM   test1 t
       JOIN test_ref tr ON(t.e_ques_id = tr.code)
GROUP BY t.e_id;

其中,对于示例数据:

CREATE TABLE test1 (e_id, e_ques_id) AS
SELECT 1, LEVEL FROM DUAL CONNECT BY LEVEL <= 5;

CREATE TABLE test_ref (code, c_value) AS
SELECT 1, 'Not this'        FROM DUAL UNION ALL
SELECT 3, 'May'             FROM DUAL UNION ALL
SELECT 4, '2022'            FROM DUAL UNION ALL
SELECT 5, 'Not this either' FROM DUAL;

输出:

E_ID MONTH_YEAR
1 May 2022

db<>fiddle here

这是你可以使用 Max() OVER() 的方法,虽然我不明白你想做什么,但也许这可以帮助...

WITH 
    test1 AS
        (
            SELECT 1 "E_ID", 3 "E_QUES_ID" FROM DUAL UNION ALL
            SELECT 1 "E_ID", 4 "E_QUES_ID" FROM DUAL UNION ALL
            SELECT 1 "E_ID", 5 "E_QUES_ID" FROM DUAL UNION ALL
            SELECT 1 "E_ID", 6 "E_QUES_ID" FROM DUAL 
        ),
    test_ref AS
        (
            SELECT 3 "CODE", 'May' "C_VALUE" FROM DUAL UNION ALL
            SELECT 4 "CODE", '2022' "C_VALUE" FROM DUAL UNION ALL
            SELECT 5 "CODE", 'Jun' "C_VALUE" FROM DUAL UNION ALL
            SELECT 6 "CODE", '2022' "C_VALUE" FROM DUAL 
        )
SELECT 
    E_ID,
    Max(LISTAGG(MY, ' ') WITHIN GROUP (ORDER BY E_ID, E_QUES_ID)) OVER() "MONTH_YEAR"
FROM
    (
        SELECT 
            t.E_ID,
            t.E_QUES_ID,
            CASE WHEN t.E_QUES_ID IN(3, 4) THEN tr.C_VALUE END "MY"
        FROM
            test1 t
        INNER JOIN 
            test_ref tr ON(t.E_QUES_ID = tr.CODE)
        ORDER BY 
            t.E_ID,
            t.E_QUES_ID
    )
GROUP BY
    E_ID