SQL構文に関しては、私は初心者です。
もちろん、行と列がたくさんあるテーブルがあります:P次のようになります。
AAA BBB CCC DDD
-----------------------
Row1 | 1 A D X
Row2 | 2 B C X
Row3 | 3 C D Z
今、私はこれを私に与える高度な選択ステートメントを作成したい(ここでは擬似SQLish):
select 'Test1', * from TABLE Where CCC='D' AND DDD='X'
select 'Test2', * from TABLE Where CCC<>'D' AND DDD='X'
出力は次のようになります。
Test1, 1, A, D, X
Test2, 2, B, C, X
これらの2つのselectステートメントを1つのNice selectステートメントに結合するにはどうすればよいですか?
以下のようにSQLを複雑にするとうまくいきますか(自分のSQL文にexists文が含まれているため)?選択を組み合わせて、それをやや高度なSQLに適用する方法を知りたいだけです。
select 'Test1', * from TABLE Where CCC='D' AND DDD='X' AND exists(select ...)
select 'Test2', * from TABLE Where CCC<>'D' AND DDD='X' AND exists(select ...)
REAL SQLステートメントは次のとおりです。
select Status, * from WorkItems t1
where exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01)
AND TimeStamp>'2009-02-12 18:00:00'
結果が得られます。しかし、最後にANDが追加されたこのselectステートメントのコピーとそれを組み合わせて、「ステータス」フィールドを「削除済み」などの文字列で変更します。
select 'DELETED', * from WorkItems t1
where exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01)
AND TimeStamp>'2009-02-12 18:00:00'
AND NOT (BoolField05=1)
ここには2つの選択肢があります。 1つは、WHERE
句の条件に基づいて 'Test1'または 'Test2'を設定し、それらを一緒にUNION
する2つの結果セットを持つことです。
select
'Test1', *
from
TABLE
Where
CCC='D' AND DDD='X' AND exists(select ...)
UNION
select
'Test2', *
from
TABLE
Where
CCC<>'D' AND DDD='X' AND exists(select ...)
TABLEを2回効果的にスキャン/シークするため、これは問題になる可能性があります。
他の解決策は、テーブルから1回選択し、TABLEの条件に基づいて「Test1」または「Test2」を設定することです。
select
case
when CCC='D' AND DDD='X' AND exists(select ...) then 'Test1'
when CCC<>'D' AND DDD='X' AND exists(select ...) then 'Test2'
end,
*
from
TABLE
Where
(CCC='D' AND DDD='X' AND exists(select ...)) or
(CCC<>'D' AND DDD='X' AND exists(select ...))
ここでのキャッチは、CASE
ステートメントとWHERE
ステートメントでフィルター条件を複製する必要があることです。
入力いただきありがとうございます。ここで言及されているものを試してみましたが、これらは私が働いた2つです:
(
select 'OK', * from WorkItems t1
where exists(select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01)
AND TimeStamp>'2009-02-12 18:00:00'
AND (BoolField05=1)
)
UNION
(
select 'DEL', * from WorkItems t1
where exists(select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01)
AND TimeStamp>'2009-02-12 18:00:00'
AND NOT (BoolField05=1)
)
そして
select
case
when
(BoolField05=1)
then 'OK'
else 'DEL'
end,
*
from WorkItems t1
Where
exists(select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01)
AND TimeStamp>'2009-02-12 18:00:00'
これらは最も効率的です(編集:2回目はテーブルを1回しかスキャンしないため)、、さらに効率的にすることが可能です ? (BoolField = 1)は実際には変数(dyn sql)であり、テーブルのwhereステートメントを含めることができます。
MS SQL 2005で実行しています。Quassnoiの例を試しましたが、期待どおりに動作しませんでした。
nionコマンドが必要なものです。 それがうまくいかない場合は、現在の環境を改善する必要があるかもしれません。
選択にケースを使用し、ORを閉じる場所で使用する
このようなもの、私はそれをテストしませんでしたが、うまくいくはずです、私は思う...
select case when CCC='D' then 'test1' else 'test2' end, *
from table
where (CCC='D' AND DDD='X') or (CCC<>'D' AND DDD='X')
私はあなたが探しているものだと思う:
SELECT CASE WHEN BoolField05 = 1 THEN Status ELSE 'DELETED' END AS MyStatus, t1.*
FROM WorkItems t1
WHERE (TextField01, TimeStamp) IN(
SELECT TextField01, MAX(TimeStamp)
FROM WorkItems t2
GROUP BY t2.TextField01
)
AND TimeStamp > '2009-02-12 18:00:00'
OracleまたはMS SQL 2005以降を使用している場合は、次のことができます。
SELECT *
FROM (
SELECT CASE WHEN BoolField05 = 1 THEN Status ELSE 'DELETED' END AS MyStatus, t1.*,
ROW_NUMBER() OVER (PARTITION BY TextField01 ORDER BY TimeStamp DESC) AS rn
FROM WorkItems t1
) to
WHERE rn = 1
、より効率的です。
select t1.* from
(select * from TABLE Where CCC='D' AND DDD='X') as t1,
(select * from TABLE Where CCC<>'D' AND DDD='X') as t2
これを行う別の方法!
select Status, * from WorkItems t1
where exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01)
AND TimeStamp>'2009-02-12 18:00:00'
UNION
select 'DELETED', * from WorkItems t1
where exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01)
AND TimeStamp>'2009-02-12 18:00:00'
AND NOT (BoolField05=1)
おそらくそれでうまくいくでしょう。ただし、ここからテストすることはできません。また、どのバージョンのSQLを対象にしているのかわかりません。