web-dev-qa-db-ja.com

GROUPBYを使用したSELECTでCASEを使用するSQL。 CASE値が必要ですが、行値を取得します

基本的に、1つの質問と1つの問題があります。

1。質問-テーブルに100個の列があり(キーまたはuindexが設定されていない)、そのテーブルをそれ自体と結合または副選択したい場合、本当にすべての列を書き出す必要がありますか?名前?

2。問題-以下の例は、1。の質問と私の実際のSQLステートメントの問題を示しています

例:

A.FIELD1,
(SELECT CASE WHEN B.FIELD2 = 1 THEN B.FIELD3 ELSE null FROM TABLE B WHERE A.* = B.*) AS CASEFIELD1
(SELECT CASE WHEN B.FIELD2 = 2 THEN B.FIELD4 ELSE null FROM TABLE B WHERE A.* = B.*) AS CASEFIELD2
FROM TABLE A
GROUP BY A.FIELD1

ストーリーは次のとおりです。CASEを独自の選択ステートメントに入れない場合、実際の行名をGROUP BYに入れなければなりません。GROUPBYはCASEからのNULL値をグループ化せず、行。そのため、キーやuindexがないため、すべての列で結合または副選択するか、何らかの方法で別の解決策を見つける必要があります。

DBServerはDB2です。

ここで、SQLを使用せずに単語だけで説明します。「ZD」と「EK」(1 = ZD、2 = EK)に分割でき、「ディストリビューター」でグループ化できる「注文アイテム」があります。 「注文アイテム」は2つの異なる「部門」(ZD、EK)のいずれかを持つことができますが、「ZD」と「EK」のフィールド/行は常に両方が入力されます。 「department」を考慮するためにグループ化する必要があり、指定された「department」(ZDまたはEK)が変更された場合にのみ、新しいグループを作成する必要があります。

SELECT
(CASE WHEN TABLE.DEPARTEMENT = 1 THEN TABLE.ZD ELSE null END) AS ZD,
(CASE WHEN TABLE.DEPARTEMENT = 2 THEN TABLE.EK ELSE null END) AS EK,
TABLE.DISTRIBUTOR,
sum(TABLE.SOMETHING) AS SOMETHING,
FROM TABLE
GROUP BY
ZD
EK
TABLE.DISTRIBUTOR
TABLE.DEPARTEMENT

これは、ここではGROUP BYのSELECTおよびZD、EKで機能しました。唯一の問題は、EKが指定されたDEPARTEMENTでなくても、変更された場合は新しいグループを開くことでした。これは、すでに上で説明したように、CASEからのNULLではなく実際のEK値を使用していたためです。

9
Khazar

そして、ここで紳士淑女が問題の解決策です:

SELECT
(CASE WHEN TABLE.DEPARTEMENT = 1 THEN TABLE.ZD ELSE null END) AS ZD,
(CASE WHEN TABLE.DEPARTEMENT = 2 THEN TABLE.EK ELSE null END) AS EK,
TABLE.DISTRIBUTOR,
sum(TABLE.SOMETHING) AS SOMETHING,
FROM TABLE
GROUP BY
(CASE WHEN TABLE.DEPARTEMENT = 1 THEN TABLE.ZD ELSE null END),
(CASE WHEN TABLE.DEPARTEMENT = 2 THEN TABLE.EK ELSE null END),
TABLE.DISTRIBUTOR,
TABLE.DEPARTEMENT

@ t-clausen.dk:ありがとう!

@others:.。

7
Khazar

実際には、ワイルドカード等価テストがあります。なぜfield1でグループ化するのかわかりませんが、この例では不可能に思えます。私はそれをあなたの質問に当てはめようとしました:

SELECT FIELD1,
CASE WHEN FIELD2 = 1 THEN FIELD3 END AS CASEFIELD1,
CASE WHEN FIELD2 = 2 THEN FIELD4 END AS CASEFIELD2
FROM 
(
 SELECT * FROM A
 INTERSECT
 SELECT * FROM B
) C
UNION -- results in a distinct
SELECT
A.FIELD1,
null,
null
FROM 
(
 SELECT * FROM A
 EXCEPT
 SELECT * FROM B
) C

これは、比較できないデータ型では失敗します

2
t-clausen.dk

このようなことを解決する傾向があるかもしれません

WITH q as
(SELECT
       Department
     , (CASE WHEN DEPARTEMENT = 1 THEN ZD
             WHEN DEPARTEMENT = 2 THEN EK
                                  ELSE null 
        END) AS GRP
     , DISTRIBUTOR
     , SOMETHING 
   FROM mytable
)
SELECT 
       Department
     , Grp
     , Distributor

     , sum(SOMETHING) AS SumTHING
  FROM q
GROUP BY
       DEPARTEMENT 
     , GRP
     , DISTRIBUTOR
1
WarrenT

いいえ、ワイルドカードの同等性テストはありません。個別にテストするすべてのフィールドをリストする必要があります。個々のフィールドをテストしたくない場合は、すべてのフィールドを連結するなどのハックを使用できます。

WHERE (a.foo + a.bar + a.baz) = (b.foo + b.bar + b.az)

ただし、いずれにしても、すべてのフィールドを一覧表示します。

1
Marc B

TableBで一致するTableAのすべての行を見つける必要がある場合、INTERSECTまたはINTERSECT DISTINCTはどうですか?

select * from A
 INTERSECT DISTINCT
select * from B

ただし、行全体がBの行の値と一致するAの行のみが必要な場合、サンプルコードでAの一部の値とBの一部の値を取得するのはなぜですか?行がすべての列で一致する場合、それは無意味に思えます。 (おそらくあなたの質問はもう少し完全に説明できますか?)

0
WarrenT