1

異なるテーブルを結合してカウントを取得する複雑なクエリがあります。グループ化するフィールドがいくつかあります。ここで、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

選択リストに追加しようとしましたが、機能しませんでした。次に、select と group by リストの 2 つの場所に追加しました。それもうまくいきませんでした。

私が得たエラーは次のとおりです。

  1. ORA-00904- CMPN が有効な列ではありません
  2. ORACLE 準備エラー: ORA-22818: サブクエリ式はここでは許可されていません。

私はオンラインでいくつかの調査を行いましたが、私のものに近いが完全に同一ではない例が見つかりました。

集計関数を使用した SQL GROUP BY CASE ステートメント ここで質問を理解したかどうかわからない count および case ステートメントを使用した SQL クエリ これは私のニーズとはかなり異なります。 http://jerrytech.blogspot.com/2008/04/can-you-group-by-case-statement-in-sql.html (これは近いですが、挿入ステートメントは必要ありません。このアプローチを試しましたが、そうではありませんでした私のために働く)

任意の提案をいただければ幸いです。

4

4 に答える 4

1

エラーは、他のようなクエリの FIELD (つまり、結果列) を記述していることだと思います: DMAGATR.WRK_LOC_LEVEL4 ,DMBR.WRK_LOC_NM ,DMBR.RELCD ,COUNT (DISTINCT DMBR.DMBRKEY...

エラーは、結果の COLUMN に SQL-Select ステートメントを使用する場合、単一の行のみを返さなければならないことだと思います。クエリは「... FROM DMBR ) as CMPN」であるため、フィールドに対して複数の行が返され、データベースは結果を推測する方法を知りません。

おそらく欠落しているのは、フィールドのWHERE句と、DMBRテーブル内から個別の値を探している場合のGROUP byの両方です。

それを修正すると、さらに先に進むはずです。残りのデータ構造や関係がわからないので、最終的な結果がどうなるかわかりません。


追加コメント...

提供された他の回答を見ると、現在の「DMBR」レコードが何であれ、すぐにCASE WHENを実行することが提案されました。これは正しいですが、完全には機能しません。考えられる2つの結果のために、それもgroup byの一部である必要があると思います..count(DISTINCT)として、group byは非集計列に基づく必要があります...そのうち、この場合/いつになるのでしょうか..だからあなたの最終的な結果は

Lvl, Work Loc, RelCD, Case/when, count(distinct)  where...
                        SEG 1     999
                        Other     999

さらに、あなたの CASE/WHEN には WHERE 句と完全に一致する 2 つのコンポーネントがありました。とにかく、そのセットのレコードが返されないため、そこから削除しました。

だから、言われていることはすべて、私はそれを次のように書くでしょう...

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

最後に、case / when などの複雑な列で group by が詰まる場所を時々見てきました。ただし、異なるサーバーでは、グループ別 (および順序別) の位置への序数参照が許可されています。したがって、クエリには 4 つの非集計列 (すべてが最初にリストされています) があるため、個別の数が表示されるため、GROUP BY 句を次のように変更することで回避できる可能性があります...

GROUP BY 1、2、3、4

SQL-Select 呼び出しを開始する列の順序に関連するすべて。

--- group by と大文字と小文字の区別に関する明確化

まず、大文字と小文字の区別です。ほとんどのエンジンはキーワードで大文字と小文字を区別します。したがって、CASE WHEN ... AND ... THEN ... ELSE ... END です。

「グループ化」(および「オーダーバイ」でも機能します)に関しては、長い名前を明示的にリストして 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テーブルは、姓と名で事前に集計され、1人あたりの合計が表示されます(この例では名前が重複していないと仮定しています。そうでない場合は、顧客IDを使用していたはずです) . それが完了すると、注文が開始され、特定の顧客への売上が最も多い順に、降順でリストの一番上に配置されます。

数値は、フィールド名を長手で入力する代わりに、クエリで返される序数の列を表すだけです。「CASE / WHEN」句の問題については、おっと再入力してグループ内で見逃してしまうのを防ぎ、髪の毛を引っ張って理由を突き止めてください。

于 2011-05-20T21:08:13.707 に答える
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
于 2011-05-20T23:59:34.040 に答える
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)
于 2011-05-20T21:11:00.587 に答える
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 
于 2011-05-20T21:20:40.690 に答える