- - PR -
直近の日付と連結するSQL文
1
投稿者 | 投稿内容 |
---|---|
|
投稿日時: 2005-09-12 14:12
環境を書き忘れていました。
SQLSERVER 8.0を使用しております。 結合を使った集計用SQLで悩んでいます。 Aテーブル(日毎・番号ごとデータ) 日付 datetime 番号 int 実績値 int … Bテーブル(機種状態) 変更日付 datetime 番号 int 機種ID int 機種の入替が発生するたびに、 その日一日の全ての機種の状態を保存する。 たとえば番号が5まであるとすると、 日付:5/10 番号:1 機種:1 番号:2 機種:1 番号:3 機種:2 番号:4 機種:3 番号:5 機種:2 日付:5/20 番号:1 機種:1 番号:2 機種:2 番号:3 機種:3 番号:4 機種:1 番号:5 機種:2 といった形の二つのテーブルがあり、 Aテーブルには日毎のデータが入っているので、これを元に 機種ごとの一ヶ月の実績値の集計などを出したいのです。 ただ、たとえば5/15の実績データについては、 5/10の機種状態から機種を判断します。 つまり、LEFT JOINする際に、Aの各レコードについて、 直近の日付のBデータを持ってきて機種を判断したいのですが、 この、直近の日付のレコードを結合するという際に良い方法はありますでしょうか。 自分で考えたのは、 SELECT 機種,SUM(実績値) FROM A LEFT JOIN B AS B1 ON A.番号 = B1.番号 AND A.日付 >= B1.日付 LEFT JOIN B AS B2 ON A.番号 = B2.番号 AND A.日付 >= B2.日付 AND B1.日付 < B2.日付 WHERE B2.日付 IS NULL GROUP BY 機種 というものです。とりあえず実績より古い日付の機種状態を全て結合し、 その後もう一つ、機種状態を結合し、そのときに機種状態1の日付より新しい日付のみ結合します。 すると最新のものは機種状態2のレコードが一件も結合されないため、値がNULLとなるので、そのレコードのみ抽出できます。 ただこれですと件数が多くなった場合にかなりパフォーマンスが落ちてしまいます。 いい手はないでしょうか。 [ メッセージ編集済み 編集者: Ishi 編集日時 2005-09-12 14:20 ] |
|
投稿日時: 2005-09-12 14:44
凄く面白い外部結合の使い方ですね
Aの日付未満で最大の日付をサブクエリとして結合条件に使用すればよいかと思います Oracleではありますが 以下のSQLを応用すればよいかと思います OracleSQLパズル http://oraclesqlpuzzle.hp.infoseek.co.jp/5-22.html http://oraclesqlpuzzle.hp.infoseek.co.jp/5-30.html |
|
投稿日時: 2005-09-12 16:37
後者のアドレスを参考にして書いてみました。
一応手元のサンプルデータでは同じ結果が出せた上にパフォーマンスもかなりあがりました。 サブクエリのWhere句で親クエリの項目と比較するという着眼点に気づけなかったのが失敗でした。 このクエリでもA,Bともにレコード数が増えると不安な点は残りますが、 そこはもう少し考えてみることにします。 ありがとうございました。 SELECT B1.機種,SUM(A.実績値) FROM A LEFT JOIN B AS B1 ON A.番号 = B1.番号 AND A.日付 >= B1.日付 WHERE B1.日付 >= (SELECT MAX(B2.日付) FROM B AS B2 WHERE A.日付 >= B2.日付) GROUP BY B1.機種 |
1