実現したいこと
以下の利用履歴(history)のテーブルから、手持ちのscidリスト(.csv)を元にselect文を作って、かつ usedateの最新のレコードを抽出し、scid が存在しない場合は意図的に1行のダミーデータを入れて一つの結果にしたいです。(ダミーでなくても、結果(理想2)のように、とにかく1行何もないデータでもOKです。)
テーブル名:history
scid | pcode | name | usedate |
---|---|---|---|
2039 | 1 | suzuki | 2004-11-18 |
1582 | 5 | hasegawa | 2016-08-10 |
2215 | 3 | tanaka | 2020-05-15 |
1582 | 2 | hasegawa | 2021-11-11 |
2039 | 2 | suzuki | 2015-10-05 |
2039 | 5 | suzuki | 2023-07-25 |
結果(理想1)
scid | pcode | usedate |
---|---|---|
2039 | 5 | 2023-07-25 |
none | none | none |
1582 | 2 | 2021-11-11 |
結果(理想2)
scid | pcode | usedate |
---|---|---|
2039 | 5 | 2023-07-25 |
1582 | 2 | 2021-11-11 |
前提
別に scid のみの一覧のリストがあって、select分を大量に発行し、実行しているのですが、scidリスト を元に select してレコードが無い場合、以下のコードのように if で処理分岐させて空のデータを意図的に流しこんでいます。
※手持ちの scid のリスト(.csv)は 約5万件ほどあります。
sql
1IF EXISTS(SELECT scid,usedate,pcode from "history" where usedate = (SELECT MAX(usedate) FROM "history" WHERE scid = '2039') and scid = '2039') 2 BEGIN 3 select scid,usedate,pcode from "history" where usedate = (SELECT MAX(usedate) FROM "history" WHERE scid = '2039') and scid = '2039' 4 END 5ELSE 6 BEGIN 7 SELECT 'none' AS scid, 'none' as usedate,'none' as pcode 8 END
単純に1処理であれば、問題ないのですが、以下のように複数同時に取得したいと思い単純にunionで結合してみました。
sql
1IF EXISTS(SELECT scid,usedate,pcode from "history" where usedate = (SELECT MAX(usedate) FROM "history" WHERE scid = '2039') and scid = '2039') 2 BEGIN 3 select scid,usedate,pcode from "history" where usedate = (SELECT MAX(usedate) FROM "history" WHERE scid = '2039') and scid = '2039' 4 END 5ELSE 6 BEGIN 7 SELECT 'none' AS scid, 'none' as usedate,'none' as pcode 8 END 9UNION 10IF EXISTS(SELECT scid,usedate,pcode from "history" where usedate = (SELECT MAX(usedate) FROM "history" WHERE scid = '99999') and scid = '99999') 11 BEGIN 12 select scid,usedate,pcode from "history" where usedate = (SELECT MAX(usedate) FROM "history" WHERE scid = '99999') and scid = '99999' 13 END 14ELSE 15 BEGIN 16 SELECT 'none' AS scid, 'none' as usedate,'none' as pcode 17 END 18
発生している問題・エラーメッセージ
unionで結合しようとすると、次のエラーが出てしまいます。。。
/* SQL エラー (156): キーワード 'IF' 付近に不適切な構文があります。 */
試したこと
SQLに関しては素人なので、方法を考えたのですがまったく思いつきません。。
補足情報(FW/ツールのバージョンなど)
使用しているSQL
Microsoft SQL Server 2008 R2 (SP2)
使用しているSQLクライアント
Heidi SQL
※その後について記入しましたが、あくまでも素人による解決の仕方です。ご指摘
その後について
neko_the_shadow さんに提示していただいたコードで見事に実現できました!が、3000件を超えたあたりでタイムアウトエラーに…
紆余曲折を得て、さらに別の方法でのコードを書いてみました。
SQL
1SELECT scid,pcode,usedate FROM "history" T1 2 WHERE NOT EXISTS ( 3 SELECT * FROM "history" T2 WHERE T1.scid = T2.scid AND T1.usedate < T2.usedate 4 ) AND scid = '2039 ' 5UNION ALL 6SELECT NULL, NULL, NULL -- 必要なだけNULL値を追加 7WHERE NOT EXISTS ( 8 SELECT scid,pcode,usedate FROM "history" T1 9 WHERE NOT EXISTS ( 10 SELECT * FROM "history" T2 WHERE T1.scid = T2.scid AND T1.usedate < T2.usedate 11 ) AND scid = '2039 ');
こちらのコードでも実現できました。
ただし、こちらでも大量にセレクト文を発行するとタイムアウトやメモリ不足でエラーが出てしまいました。
その他の解決方法へ
- メモリ不足については、一時テーブルを作って回避できるかな?
- タイムアウトについては、処理を分割して実行すれば問題ないかな?
ということで、試してみました。
一時テーブルを作成
SQL
1CREATE TABLE "#tmp_history"( -- テーブル名の頭に # をつけることで一時的なテーブルを作成できる 2 scid VARCHAR(100) NULL 3 ,usesdate date NULL 4 ,pcode varchar(100) NULL 5)
セレクトしつつ、作成した一時テーブル #tmp_history へインサートする。
これ1処理1行にまとめて手持ちのscid分コードを生成…手持ちのscidリスト(.csv)は、全部で5万件あるので
一度にすべてでなく SQLファイルに 処理を3000件ずつ分けて list_01.sql~list_17.sql ファイルを生成。
SQL
1INSERT INTO "#tmp_history" (scid,usedate,pcode) 2SELECT TOP(1) scid,usedate,pcode FROM "history" T1 3 WHERE NOT EXISTS ( 4 SELECT * FROM "history" T2 5 WHERE T1.scid = T2.scid AND T1.usedate < T2.usedate 6 ) AND scid = '69112' 7UNION ALL 8SELECT NULL, NULL, NULL 9 WHERE NOT EXISTS ( 10 SELECT scid,pcode,usedate FROM "history" T1 11 WHERE NOT EXISTS ( 12 SELECT * FROM "history" T2 13 WHERE T1.scid = T2.scid AND T1.usedate < T2.usedate 14 ) AND scid = '69112' 15 );
HeidiSQLクライアントにて、[ファイル]→[SQLファイルを実行]で作成したSQLファイルすべて選択して
全ての処理を終えました。
取り急ぎこのような流れで解決しましたので、参考になればと思います。

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/08/15 03:44
2023/08/15 04:15