dポイントプレゼントキャンペーン実施中!

あるテーブルから、指定した期間のデータを抽出したいのですが、うまく取れません。

テーブル:RecData
SortID iYear iMonths Amount
--------------------------------------------
 1   2002  3   100
 1   2002  4   113
 :    :   :   :
 1   2008  7   112
 1   2008  8   102
 2   2002  3   40
 2   2002  4   34
 :    :   :   :
 2   2008  7   43
 2   2008  8   41

上記のようなテーブルがあるのですが、すべて数値型です。
このテーブルから、「SortIDが1で、2002年5月から2003年4月のデータ」を検索するにはどのようにしたら良いでしょうか?
「Select * from RecData Where SortID = 1 And iYear = 2002 And iMonths >= 5 Or SortID = 1 And iYear = 2003 And iMonths <= 4」
のようなやり方だと、「2002/04から2005/03」のような期間は正しく取れません。
その場合は1年づつループしなければ取れないでしょうか。
よろしくお願い致します。

使用しているDBはSQLServer2000 で、VBからSQL文を作成しています。
 

A 回答 (7件)

# 現在手元にSQL Serverの環境もリファレンスもないので、検証できない状態ですが....。



厳密に日付型として評価させたいなら、CASTを使用して

WHERE
CAST(CAST(iYear AS VARCHAR) + '/' + CAST(iMonths AS VARCHAR)+ '/01' AS DATETIME)
BETWEEN
2002/05/01 AND 2003/04/30

のようにする必要がありそうです。
それよりは、日付型に拘らずに、

WHERE
(iYear * 100 + iMonths)
BETWEEN
200205 AND 200304

と数値型で処理した方が簡単です。
(No.2さんの案とほとんど同じですが....)
この方法なら、四則演算以外の知識を必要としないので、小学生でも実装が可能という利点があります。


# いずれにせよ、WHERE句の左辺で演算を行うので、途轍もなく遅そうなSQLですが....。


> 1年づつループしなければ取れないでしょうか。
お金が毟れる客が相手なら、最初は意図的に性能の悪い作りにしておいて、「チューニング」と称して後から予算を請求する戦略も考えられます。
    • good
    • 1
この回答へのお礼

どんな評価方法でも取れれば良いです。
なのでCASTより四則演算の方が簡単ですね。
しかもConvertも使わなくてすむし…。
実際に書いてやってみましたが、四則演算で取れてしまうし。
今まで取れなかった数年にまたがった期間もバッチリですね。

チューニングと称して予算を請求する戦略で、設計時に年と月が別で日付型にしなかったなんてことは…ないよなぁ…。今から「チューニング」するとVB側のSQL文を全部書き直しになるから違うでしょうねぇ。

ありがとうございます。

お礼日時:2004/03/10 10:49

VBでSQL文を生成する、とのことですので、If条件で場合訳をする必要がありそうです。



# WHERE句にORが多い場合、UNIONで繋いだほうがパフォーマンスが高いかも....。(邪道??)
    • good
    • 0
この回答へのお礼

何度もありがとうございます。
やはりVB側の分岐条件でバグを作りこむ方が不安なもので
今回はパフォーマンスは見送る事にします。(~_~;)

お礼日時:2004/03/10 18:35

>が、やはり「2002年から2005年」のように、終了年が開始年の翌年で無い場合は


>「iYear = 2002」「iYear = 2003」を「iYear >= 2002」「iYear <= 2003」にしても
>ダメですよね

where
SortID = 1 And
((iYear = 2002 And iMonths >= 5)
or
(iYear = 2005 And iMonths <= 4)
or
(iYear > 2002 And iYear < 2005 And ))
    • good
    • 0
この回答へのお礼

何度もありがとうございます。
やはりOR でつなげていくんですね。
指定期間によってはVB側の分岐が複雑になりそうなので
今回はパフォーマンスは無視する事にいたします。

お礼日時:2004/03/10 18:31

>冷静に見直してみると、No.1のSQLが最速のように見えます。



というか、最速です。
ちなみに#1のSQL以外は、iYearやiMonthsにインデックスをはっても効果がありません。
つまり、チューニングもできません。

#SortID、iYear、iMonthsの組が主キーだったらコストベースならインデックス勝手に使ってくれるかも


検索条件において、フィールドに対して関数を使ったり演算を行った場合、インデックスはそのフィールドに存在しても使用されません。
関数を使ったり、演算するのは最後の手段です。
    • good
    • 0
この回答へのお礼

え…?!チューニングもできないのですか?!
検索条件で演算しちゃうと、インデックスは無意味ですか。

複雑なSQLで1度で取るか、何度かSelect文を発行するか悩む時もありますが。

やろうとしてることは最後の手段だったのですね。
参考になりました。
ありがとうございます。

お礼日時:2004/03/10 11:01

冷静に見直してみると、No.1のSQLが最速のように見えます。

    • good
    • 0
この回答へのお礼

最速、ですか。
これで数年にわたって簡単に取れるなら問題なかったんですが。
うーん、なんであーいうテーブル設計になっているのかナゾです。
この際、ノロくてもヨイです。(~_~;)
助かりました。m(_ _)m

お礼日時:2004/03/10 10:53

convert を使用して文字列にしてから連結して


200203
200204
200205
のような形にしたものに対して範囲指定してやればいいんじゃないでしょうか。
    • good
    • 0
この回答へのお礼

sql初心者なもので、convert がよく判っていないのですが…
文字連結してから数値に戻して大小比較ですか?
おお、いいかもしれません。
convert のお勉強をいたします。
ありがとうです。

お礼日時:2004/03/10 10:31

where


SortID = 1 And
((iYear = 2002 And iMonths >= 5)
or
(iYear = 2003 And iMonths <= 4))
    • good
    • 0
この回答へのお礼

この方法で試してみたところ、「2002/5~2003/4」は
ちゃんと取得できました。
が、やはり「2002年から2005年」のように、終了年が開始年の翌年で無い場合は「iYear = 2002」「iYear = 2003」を「iYear >= 2002」「iYear <= 2003」にしてもダメですよね…。

お礼日時:2004/03/10 10:25

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!