使用分组字段中的case语句进行SQL查询

| 我有一个复杂的查询,它连接不同的表以获取计数。有一些字段可以分组。现在,我想添加一个需要case语句的附加字段。并且此字段也必须在“分组依据”列表中。我的查询原本是这样的-
SELECT DMAGATR.WRK_LOC_LEVEL4 
     , DMBR.WRK_LOC_NM 
     , DMBR.RELCD 
     , COUNT(DISTINCT DMBR.DMBRKEY) AS ELIG_COUNT
      FROM DMBR 
INNER JOIN DCUST DCUST ON DMBR.DCUSTKEY = DCUST.DCUSTKEY
INNER JOIN DMAGATR DMAGATR ON DMBR.DMBRKEY = DMAGATR.DMBRKEY
 LEFT JOIN DMDYNATR DMDYNATR ON DMBR.DMBRKEY = DMDYNATR.DMBRKEY
     WHERE DMBR.C_TIMESSTAMP <= \'12/31/2011\'
       AND DMBR.RELCD IN (\'0\', \'1\') 
       AND DMBR.EE_STS IN ( \'A\',\'L\')
       AND (DMBR.DEL_DT IS NULL
        OR DMBR.DEL_DT > \'12/31/2011\')
       AND DCUST.PRCD = \'TAR\'
  GROUP BY DMAGATR.WRK_LOC_LEVEL4, DMBR.WRK_LOC_NM, D_MEMBER.REL_CD
但是新领域看起来像这样-
(SELECT CASE
          WHEN (DMBR.WRK_LOC_NM = \'6\' AND DMBR.GDR = \'M\' AND DMBR.REL_CD in (\'0\',\'1\') 
            AND DMBR.EE_STS IN (\'A\',\'L\')) THEN \'SEG 1\'
          ELSE \'OTHER\'
        END 
   FROM DMBR) as CMPN
我试图将其添加到选择列表中,但没有成功。然后,我将其添加到两个位置-在选择列表中以及在“分组依据”列表中。那也不起作用。 我得到的错误是:
ORA-00904
-CMPN无效的列 ORACLE准备错误:“ 3”:此处不允许使用子查询表达式。 我在网上进行了一些研究,发现一些示例与我的示例相似但并不完全相同。 具有聚合功能的SQL GROUP BY CASE语句 不知道我是否明白这里的问题 带计数和大小写语句的SQL查询 这与我的需求完全不同。 http://jerrytech.blogspot.com/2008/04/can-you-group-by-case-statement-in-sql.html (这很接近,但是我不需要用插入语句尝试这种方法,但是对我来说不起作用) 任何建议,将不胜感激。     
已邀请:
我认为错误是您正在像其他查询一样描述查询的字段(即结果列):DMAGATR.WRK_LOC_LEVEL4,DMBR.WRK_LOC_NM,DMBR.RELCD,COUNT(DISTINCT DMBR.DMBRKEY ... 我认为错误是当对结果的COLUMN使用SQL-Select语句时,它只能返回单行。由于您的查询只是\“ ... FROM DMBR,如CMPN \\”,因此您将为该字段返回多个行,并且没有数据库知道如何猜测结果。 如果您要从DMBR表中查找不同的值,则可能缺少的是字段上的WHERE子句,也可能是GROUP BY。 解决该问题,它可以使您进一步前进。不知道其余的数据结构或关系,我无法弄清楚您的最终结果是什么。 其他评论... 通过查看提供的其他答案,他们提供了立即对您正在使用的当前“ DMBR”记录进行案例分析,这是正确的,但效果并不理想。我认为,由于两种可能的结果,也必须成为group by的一部分..作为count(DISTINCT),group by必须基于任何非聚合列...在这种情况下,什么时候会这样..所以您的最终结果将有
Lvl, Work Loc, RelCD, Case/when, count(distinct)  where...
                        SEG 1     999
                        Other     999
另外,您的CASE / WHEN具有两个与您的WHERE子句完全匹配的组件,因此我将其从那里删除,因为无论如何都不会返回该集合的记录。 所以,话虽这么说,我会写成...
SELECT
      DMAGATR.WRK_LOC_LEVEL4,
      DMBR.WRK_LOC_NM,
      DMBR.RELCD,
      CASE WHEN (DMBR.WRK_LOC_NM = \'6\' 
             AND DMBR.GDR = \'M\' ) 
           THEN \'SEG 1\'
           ELSE \'OTHER\'
           END as WhenStatus,
      COUNT (DISTINCT DMBR.DMBRKEY) AS ELIG_COUNT
   FROM
      DMBR 
         JOIN DCUST 
            ON  DMBR.DCUSTKEY = DCUST.DCUSTKEY
         JOIN DMAGATR
            ON  DMBR.DMBRKEY = DMAGATR.DMBRKEY
         LEFT JOIN DMDYNATR
            ON  DMBR.DMBRKEY = DMDYNATR.DMBRKEY
   WHERE
          DMBR.C_TIMESSTAMP <= \'12/31/2011\'
      AND DMBR.REL_CD in (\'0\',\'1\') 
      AND DMBR.EE_STS IN (\'A\',\'L\')) 
      AND DCUST.PRCD = \'TAR\'
      AND (    DMBR.DEL_DT IS NULL
           OR  DMBR.DEL_DT > \'12/31/2011\')
   GROUP BY 
      DMAGATR.WRK_LOC_LEVEL4,
      DMBR.WRK_LOC_NM,
      D_MEMBER.REL_CD,
      CASE WHEN (DMBR.WRK_LOC_NM = \'6\' 
            AND DMBR.GDR = \'M\' ) 
          THEN \'SEG 1\'
          ELSE \'OTHER\'
          END
最终,有时,我已经看到group by将阻塞复杂的列,例如case / when。但是,不同的服务器允许按位置(也按顺序)对组进行顺序引用。因此,由于查询具有4个非聚合列(所有列都首先列出),然后是不重复计数,因此您可以将GROUP BY子句更改为... 按1、2、3、4分组 所有这些都与STARTING the SQL-Select调用的列的顺序有关。 ---关于分组依据和区分大小写的澄清 首先,区分大小写,大多数引擎对关键字都是区分大小写的,因此,当... AND ... THEN ... ELSE ... END时为CASE。 至于\“ group by \”(也适用于\“ order by \”),它更像是查询中序数列的快捷方式,而不必为它们明确列出长名称并必须重新输入整个CASE构造第二次,您可以通过查看以下(不相关的)查询,让引擎知道要排序结果集的哪一列...
select
      lastname,
      firstname,
      sum( orderAmount ) TotalOrders
   from
      customerOrders
   group by
      lastname,
      firstname
   order by 
     TotalOrders DESC
select
      lastname,
      firstname,
      sum( orderAmount ) TotalOrders
   from
      customerOrders
   group by
      1,
      2
   order by 
      3 DESC
每个人都会产生相同的结果...虚构的customerOrders表将按姓氏和名字进行预先汇总,并显示每人的总数(均假设此示例中没有重复的名称,否则,我将使用客户ID) 。完成此操作后,订单将按顺序排列,并将以列表的DESCENDING顺序按给定客户的最大销售额进行排序。 这些数字仅表示查询中返回的序数列,而不是长时间键入字段名称。有关您的\“ CASE / WHEN \”子句的问题的更多信息,以防止哎呀重新键入并通过找出原因来使它们在组中丢失。     
如果其他答案不起作用,您也可以尝试这种(派生子查询)方法:
SELECT
      WRK_LOC_LEVEL4,
      WRK_LOC_NM,
      RELCD,
      CMPN,
      COUNT (DISTINCT DMBRKEY) AS ELIG_COUNT
FROM
  ( SELECT
          DMAGATR.WRK_LOC_LEVEL4,
          DMBR.WRK_LOC_NM,
          DMBR.RELCD,
          CASE WHEN (DMBR.WRK_LOC_NM = \'6\' 
                 AND DMBR.GDR = \'M\' ) 
               THEN \'SEG 1\'
               ELSE \'OTHER\'
          END
            AS CMPN,
          DMBR.DMBRKEY
       FROM
          DMBR 
             JOIN DCUST 
                ON  DMBR.DCUSTKEY = DCUST.DCUSTKEY
             JOIN DMAGATR
                ON  DMBR.DMBRKEY = DMAGATR.DMBRKEY
             LEFT JOIN DMDYNATR
                ON  DMBR.DMBRKEY = DMDYNATR.DMBRKEY
       WHERE
              DMBR.C_TIMESSTAMP <= \'12/31/2011\'
          AND DMBR.REL_CD in (\'0\',\'1\') 
          AND DMBR.EE_STS IN (\'A\',\'L\')) 
          AND DCUST.PRCD = \'TAR\'
          AND (    DMBR.DEL_DT IS NULL
               OR  DMBR.DEL_DT > \'12/31/2011\')
  ) AS TMP
GROUP BY 
   WRK_LOC_LEVEL4,
   WRK_LOC_NM,
   REL_CD,
   CMPN
    
我不完全了解您在“ SELECT列表中”的意思。我不知道为什么CMPN包含自己的SELECT。您是否正在尝试执行以下操作,否则,目标是什么?
SELECT  
DMAGATR.WRK_LOC_LEVEL4 
,DMBR.WRK_LOC_NM 
,DMBR.RELCD 
,COUNT (DISTINCT DMBR.DMBRKEY) AS ELIG_COUNT
,(CASE
   WHEN (DMBR.WRK_LOC_NM = \'6\' 
   AND DMBR.GDR = \'M\' 
   AND DMBR.REL_CD in (\'0\',\'1\') 
   AND DMBR.EE_STS IN (\'A\',\'L\')) 
 THEN \'SEG 1\'
 ELSE \'OTHER\'
END     
) as CMPN
FROM DMBR 
INNER JOIN  DCUST DCUST
    ON  DMBR.DCUSTKEY = DCUST.DCUSTKEY
INNER JOIN   DMAGATR DMAGATR
    ON  DMBR.DMBRKEY = DMAGATR.DMBRKEY
LEFT JOIN   DMDYNATR DMDYNATR
    ON  DMBR.DMBRKEY = DMDYNATR.DMBRKEY
WHERE    DMBR.C_TIMESSTAMP <= \'12/31/2011\'
AND DMBR.RELCD IN (\'0\', \'1\') 
AND DMBR.EE_STS IN ( \'A\',\'L\')
AND (DMBR.DEL_DT IS NULL
OR  DMBR.DEL_DT > \'12/31/2011\')
AND     DCUST.PRCD = \'TAR\'
GROUP BY 
     DMAGATR.WRK_LOC_LEVEL4
    ,DMBR.WRK_LOC_NM
    ,D_MEMBER.REL_CD
    ,(CASE
   WHEN (DMBR.WRK_LOC_NM = \'6\' 
   AND DMBR.GDR = \'M\' 
   AND DMBR.REL_CD in (\'0\',\'1\') 
   AND DMBR.EE_STS IN (\'A\',\'L\')) 
 THEN \'SEG 1\'
 ELSE \'OTHER\'
END)
    
    SELECT  
    DMAGATR.WRK_LOC_LEVEL4 
    ,DMBR.WRK_LOC_NM 
    ,DMBR.RELCD 
    ,COUNT (DISTINCT DMBR.DMBRKEY) AS ELIG_COUNT,
    (SELECT 
     CASE
    WHEN (DMBR.WRK_LOC_NM = \'6\' 
    AND DMBR.GDR = \'M\' 
    AND DMBR.REL_CD in (\'0\',\'1\') 
    AND DMBR.EE_STS IN (\'A\',\'L\')) 
    THEN \'SEG 1\'
    ELSE \'OTHER\'
    END     
    ) as CMPN
    FROM DMBR 
    INNER JOIN  DCUST DCUST
        ON  DMBR.DCUSTKEY = DCUST.DCUSTKEY
    INNER JOIN   DMAGATR DMAGATR
        ON  DMBR.DMBRKEY = DMAGATR.DMBRKEY
    LEFT JOIN   DMDYNATR DMDYNATR
        ON  DMBR.DMBRKEY = DMDYNATR.DMBRKEY
    WHERE    DMBR.C_TIMESSTAMP <= \'12/31/2011\'
    AND DMBR.RELCD IN (\'0\', \'1\') 
    AND DMBR.EE_STS IN ( \'A\',\'L\')
    AND (DMBR.DEL_DT IS NULL
    OR  DMBR.DEL_DT > \'12/31/2011\')
    AND     DCUST.PRCD = \'TAR\'
    GROUP BY 
    DMAGATR.WRK_LOC_LEVEL4
    ,DMBR.WRK_LOC_NM
    ,D_MEMBER.REL_CD,  DMBR.GDR, DBMR.EE_STS 
    

要回复问题请先登录注册