【问题标题】:SQL LISTAGG query is not creating a concatenated stringSQL LISTAGG 查询未创建连接字符串
【发布时间】:2019-02-13 21:20:18
【问题描述】:

我正在尝试使用 Oracle LISTAGG 创建基于行的串联值字符串。这是仍然显示我正在尝试解决的问题的简化代码。

SELECT S_SUBJECT.UNIQRECNUM,                      
(SELECT LISTAGG(S_STUDY.U_PRIMARYRESEARCHCOHORT,',') WITHIN GROUP ( 
     ORDER BY U_PRIMARYRESEARCHCOHORT)
     FROM S_STUDY
     WHERE S_STUDY.S_STUDYID = S_PARTICIPANT.SSTUDYID) COHORTS

FROM S_SUBJECT
JOIN S_PARTICIPANT ON S_PARTICIPANT.SUBJECTID = S_SUBJECT.S_SUBJECTID
WHERE S_SUBJECT.UNIQRECNUM IN ('9','8','7','6','5','2');


These are the results of this query;
UNIQRECNUM | COHORTS
---------------------
    2      | Gastro
    5      | Metabolic
    6      | Cardio
    7      | Cardio
    8      | Gastro
    8      | Cardio
    9      | Gastro
    9      | Gastro
    9      | Gastro


What I am expecting to see from LISTAGG would be
UNIQRECNUM  | COHORTS
--------------------
    2       | Gastro
    5       | Metabolic
    6       | Cardio
    7       | Cardio
    8       | Cardio,Gastro
    8       | Cardio,Gastro
    9       | Gastro,Gastro,Gastro
    9       | Gastro,Gastro,Gastro
    9       | Gastro,Gastro,Gastro

【问题讨论】:

    标签: sql oracle listagg


    【解决方案1】:

    我相信您的查询会是这样的:

    SELECT S_SUBJECT.UNIQRECNUM,                      
      LISTAGG(S_STUDY.U_PRIMARYRESEARCHCOHORT,',') WITHIN GROUP ( 
         ORDER BY U_PRIMARYRESEARCHCOHORT) COHORTS
    FROM S_SUBJECT
    JOIN S_PARTICIPANT ON S_PARTICIPANT.SUBJECTID = S_SUBJECT.S_SUBJECTID
    JOIN S_STUDY ON S_STUDY.S_STUDYID = S_PARTICIPANT.SSTUDYID
    WHERE S_SUBJECT.UNIQRECNUM IN ('9','8','7','6','5','2')
    GROUP BY S_SUBJECT.UNIQRECNUM;
    

    【讨论】:

      【解决方案2】:

      为什么不

      select u.uniqrecnum,
        listagg(t.u_primarysearchcohort, ',') 
          within group (order by t.u_primarysearchcohort) cohorts
      from s_subject u join s_study t on t.s_studyid = p.sstudyid
      join s_participant p on p.subjectid = u.s_subjectid
      where u.uniqrecnum in ('9','8','7','6','5','2')
      group by u.uniqrecnum;
      

      【讨论】:

        【解决方案3】:

        试试这个:

        样本数据:

        UNIQRECNUM COHORTS  
        ---------- ---------
                 2 Metabolic
                 5 Cardio   
                 6 Cardio   
                 7 Gastro   
                 8 Gastro   
                 8 Cardio   
                 9 Gastro   
                 9 Gastro   
                 9 Gastro   
        
        WITH T AS 
        (
            SELECT 2 AS  UNIQRECNUM,'Metabolic' AS COHORTS FROM DUAL
            UNION ALL
            SELECT 5 AS  UNIQRECNUM,'Cardio' AS COHORTS FROM DUAL
            UNION ALL
            SELECT 6 AS  UNIQRECNUM,'Cardio' AS COHORTS FROM DUAL
            UNION ALL
            SELECT 7 AS  UNIQRECNUM,'Gastro' AS COHORTS FROM DUAL
            UNION ALL
            SELECT 8 AS  UNIQRECNUM,'Gastro' AS COHORTS FROM DUAL
            UNION ALL
            SELECT 8 AS  UNIQRECNUM,'Cardio' AS COHORTS FROM DUAL
            UNION ALL
            SELECT 9 AS  UNIQRECNUM,'Gastro' AS COHORTS FROM DUAL
            UNION ALL
            SELECT 9 AS  UNIQRECNUM,'Gastro' AS COHORTS FROM DUAL
            UNION ALL
            SELECT 9 AS  UNIQRECNUM,'Gastro' AS COHORTS FROM DUAL
        )
        SELECT UNIQRECNUM,
             LISTAGG(COHORTS,',') WITHIN GROUP ( 
             ORDER BY COHORTS) OVER (PARTITION BY UNIQRECNUM) AS COHORTS 
        FROM T;          
        

        输出:

        UNIQRECNUM COHORTS                                                                                             
        ---------- ----------------------
                 2 Metabolic                                                                                           
                 5 Cardio                                                                                              
                 6 Cardio                                                                                              
                 7 Gastro                                                                                              
                 8 Cardio,Gastro                                                                                       
                 8 Cardio,Gastro                                                                                       
                 9 Gastro,Gastro,Gastro                                                                                
                 9 Gastro,Gastro,Gastro                                                                                
                 9 Gastro,Gastro,Gastro              
        

        【讨论】:

          【解决方案4】:

          我想你想要一个窗口函数:

          SELECT su.UNIQRECNUM,                      
                 LISTAGG(st.U_PRIMARYRESEARCHCOHORT, ',') WITHIN GROUP
                             (ORDER BY U_PRIMARYRESEARCHCOHORT) OVER (PARTITION BY su.UNIQRECNUM) as COHORTS
          FROM S_SUBJECT su JOIN
               S_PARTICIPANT p
               ON p.SUBJECTID = su.S_SUBJECTID JOIN
               S_STUDY st
               ON st.S_STUDYID = p.SSTUDYID
          WHERE su.UNIQRECNUM IN ('9', '8', '7', '6', '5', '2');
          

          【讨论】:

          • 更正:(1)将分区拼写为分区(2)在更正这些错误后,s.UNIQRECNUM 应该是 su.UNIQRECNUM 我仍然遇到错误。 ORA-00904: "S_STUDY"."U_PRIMARYRESEARCHCOHORT": 标识符无效 我检查了表,列存在并且拼写正确。