2011-05-20 27 views
1

我有一個複雜的查詢,它連接不同的表以獲取計數。有幾個領域要分組。現在,我想添加一個需要case語句的附加字段。而且這個領域也必須在分組列表中。我最初的查詢看起來像這樣 -在字段組中按字段使用case語句的SQL查詢

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 

我試着將它添加在選擇列表中,但沒有奏效。然後我將它添加到兩個地方 - 選擇和分組列表中。那也行不通。

我是該錯誤:

  1. ORA-00904 - CMPN不是有效的列
  2. ORACLE準備的錯誤:ORA-22818:子查詢表達式這裏不允許。

我在網上做了一些研究,發現接近但並不完全等同於我的例子。

SQL GROUP BY CASE statement with aggregate function 不知道我理解的問題在這裏 SQL query with count and case statement 這是我需要完全不同的。 http://jerrytech.blogspot.com/2008/04/can-you-group-by-case-statement-in-sql.html (這是接近,但我不需要插入聲明,我試過這種方法,但它並沒有爲我工作)

任何意見,將不勝感激。

回答

1

我認爲錯誤是你所描述的一個字段(即:結果列)爲其他類似查詢:DMAGATR.WRK_LOC_LEVEL4,DMBR.WRK_LOC_NM,DMBR.RELCD,COUNT(DISTINCT DMBR.DMBRKEY ...

我認爲錯誤是,當爲一個結果COLUMN使用一個SQL-Select語句時,它必須只返回一行,因爲你的查詢只是「... FROM DMBR),如同CMPN」,你返回多個行爲字段,沒有數據庫知道如何猜測你的結果。

如果您正在DMBR表內尋找不同的值,您可能缺少的是該字段上的WHERE子句以及可能的GROUP BY。

修復它,它應該讓你更進一步。不知道數據結構或關係的其餘部分,我無法確定你的最終結果是什麼。


進一步置評...

通過查看提供其他的答案,他們願意做一個直接的CASE WHEN在任何當前的「DMBR」記錄你在,這將是正確的,但不太工作。我認爲,由於這兩個可能的結果,這也必須成爲該組織的一部分,作爲計數(DISTINCT),該組必須基於任何非聚合列......其中,這種情況/什麼時候會這樣。所以,你最終的結果將有

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 

最後,有時候,我看到其中一組被噎死一個複雜列,如情況/什麼時候。但是,不同的服務器允許按(並按順序排列)位置依次引用組。因此,由於查詢有4個非聚合列(全部列在第一位),因此計數不同,您可能可以通過將GROUP BY子句更改爲...

GROUP BY 1,2, 3,4

所有與列的順序相關的啓動SQL-Select調用。

---澄清有關組和區分大小寫

首先,區分大小寫,大多數發動機是大小寫敏感的關鍵詞,因此CASE WHEN ... AND ... THEN ... ELSE ... 結束。

至於「group by」(也適用於「order by」),它更像是查詢中序號列的快捷方式,而不是明確列出長名稱並重新輸入整個案件建造第二個時間,你可以讓引擎知道設定您看看下面的(無關)查詢訂購其結果列...

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」條款的問題,以防止哎呀重新鍵入並在組中錯過了,並拉出你的頭髮找出原因。

+0

我認爲你有一個點那裏。我最初的做法是有兩個查詢 - 一個用於分配每個記錄(DMBR中有100000+)一個CMPN,第二個用於根據該字段進行總計。我正在研究的是在同一個查詢中執行這兩個操作的方法。 – saspert 2011-05-20 21:27:26

+0

@saspert,查詢修改後的答案,查詢 – DRapp 2011-05-20 23:29:38

+0

您的建議似乎有效 - 雖然我想了解您的筆記在查詢。我從來沒有嘗試1,2,3,4組。我似乎注意到EXACT CASE語句需要在兩個地方。即使是輕微的變化也會導致錯誤。 – saspert 2011-05-23 19:00:35

1

我不確切地知道你的意思是「在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) 
+0

「Select List」指的是所有到此處的字段SELECT DMAGATR.WRK_LOC_LEVEL4,DMBR.WRK_LOC_NM,DMBR.RELCD .....我嘗試了你的查詢,但是我得到了第二個錯誤(ORACLE準備錯誤:ORA-22818:這裏不允許使用子查詢表達式) – saspert 2011-05-20 21:32:07

+0

最後一個''''指的是哪裏? – 2011-05-20 23:50:14

+0

@ypercube:看起來像複製/粘貼錯誤,將會更正 – 2011-05-21 02:08:16

0
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 
+0

這是我試過的。這沒有成功。我可以知道爲什麼你在組中按字段添加EE_STS。總不需要基於此。 – saspert 2011-05-20 21:31:27

1

你也可以試試這個(派生子查詢)的方法,如果其他的答案不工作:

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 
+0

非常感謝您的建議 - 但是對原始查詢進行一些編輯似乎對我有用。 – saspert 2011-05-23 18:55:48