- PR -

複数フィールドに対しての検索方法

1
投稿者投稿内容
ともこ
大ベテラン
会議室デビュー日: 2007/09/14
投稿数: 111
投稿日時: 2008-02-23 10:21
お世話になります。
SQLサーバー2000(SP4)を使用しています。

以下のように「月」と「日にち」と別々のフィールドがあるテーブルから「01月31日〜02月02日」のデータを抽出したい場合、どのようなSELECT文を実行すれば良いのでしょうか?
■テーブルA================
月   |日にち   
-------------------
01   |01
01   |02
01   |03
〜〜〜〜〜〜〜〜〜
〜〜〜〜〜〜〜〜〜
01   |30
01   |31
02   |01
02   |02
02   |03
==========================
1つのフィールドからならBETWEENでSELECTできるのですが、複数のフィールドだとどのようにして良いか分かりません。どなたかアドバイスを頂けないでしょうか?


Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2008-02-23 10:40
WHERE 月 + 日にち BETWEEN '0131' AND '0202'

となります。
忠犬
大ベテラン
会議室デビュー日: 2006/05/01
投稿数: 109
投稿日時: 2008-02-23 11:21
引用:

Anthyhimeさんの書き込み (2008-02-23 10:40) より:
WHERE 月 + 日にち BETWEEN '0131' AND '0202'

となります。



「月 + 日」などのように、列を加工・演算すると、仮に「月」や「日」の列にインデクスが
あっても、多くのRDBMSでは利用してくれません。

性能を重視するなら、面倒でも次のような条件指定を行います。

コード:
where 月='01' and 日>='31'
     or 月='02' and 日<='02'



1月31日から3月02日なら、次のようになります。

コード:
where 月='01' and 日>='31'
   or 月='02'
   or 月='03' and 日<='02'




月日を別々の列にするより、1個の列にしてしまった方が、シンプルで性能がでる
操作にできるように思います。検索結果を、月と日に分けるだけなら、大きな性能
劣化になりません。

コード:
select substring(月日,1,2) as 月,substring(月日,3,2) as 日
 from t1
 where 月日 between '0131' and '0202'




以下、参考まで。

(1)SQL Server 2000、2005でも未実装なのですが、主要なRDBMSでは、SQL-99で
 規定された行値構成子(行値式)が実装されています。

コード:
  where (月,日) >= ('01,31') and (月,日) <= ('02,02') 



(2)RDBMSによっては、「月+日」でインデクスを定義可能なものもあり、この場合は、
 「月+日」の検索条件でもインデクスを活用できます。
ともこ
大ベテラン
会議室デビュー日: 2007/09/14
投稿数: 111
投稿日時: 2008-02-23 11:56
Anthyhimeさん、忠犬さん、アドバイスありがとうございます。

Anthyhimeさんのアドバイスを試したところ、
R/3のSQLに対しては実行できるのですが、AS/400のDB2に対しては以下のようなエラーが表示され「+」が使用出来ませんでした。データベースによって多少異なるのかもしれません。
■エラー-------------------------------------------------------
サーバー : メッセージ 7399、レベル 16、状態 1、行 11
OLE DB プロバイダ 'IBMDA400' はエラーをレポートしました。
[OLE/DB provider returned message: SQL0402: +の使用法が正しくない。
原因−−算術関数または演算子+に正しくないオペランドが指定されています。
---------------------------------------------------------------

忠犬さんのアドバイスは非常に為になりました。
パフォーマンス面等を考えても「月」と「日にち」は「月日」フィールドとして管理するのが私的にも好ましく思います。しかし既存のデータベースの為、うまく立ち回るしかなさそうです^^;

@where 月='01' and 日>='31'
     or 月='02' and 日<='02'
Awhere 月='01' and 日>='31'
     or 月='02'
     or 月='03' and 日<='02'

上記@とAについて、
日付の選択範囲が2ヶ月なら@のSQL文でも比較的対応は容易なのですが、
3ヶ月以上になると「or 月='××'」の部分が多くなってしまいますよね?
また動的にSQL文を作成するような仕組みを考えなければなりません。
なかなか難しいですね><;



未記入
大ベテラン
会議室デビュー日: 2008/02/07
投稿数: 115
投稿日時: 2008-02-23 12:37
意味が分からん。SQL Server 2000 (SP4) なんじゃないの?
月と日をくっつけた計算列を作って計算列にインデックス張っとけばいいよ。
ともこ
大ベテラン
会議室デビュー日: 2007/09/14
投稿数: 111
投稿日時: 2008-02-23 16:01
未記入さん、私の環境はSQL Server 2000 (SP4)です。
しかし、OPENQUERYを使用してR/3やAS/400のデータも扱っている為、アドバイス頂いた内容についてR/3やAS/400に対しても確認してみました。
変な誤解を与えてしまったのでしたら謝まります。
失礼します。
忠犬
大ベテラン
会議室デビュー日: 2006/05/01
投稿数: 109
投稿日時: 2008-02-23 19:06
引用:

上記@とAについて、
日付の選択範囲が2ヶ月なら@のSQL文でも比較的対応は容易なのですが、
3ヶ月以上になると「or 月='××'」の部分が多くなってしまいますよね?
また動的にSQL文を作成するような仕組みを考えなければなりません。
なかなか難しいですね><;



[or 月='xx'」を、「or 月>='xx' and 月<='xx'」という条件式にしておけばいいのでは?

引用:

R/3のSQLに対しては実行できるのですが、AS/400のDB2に対しては以下のようなエラーが表示され「+」が使用出来ませんでした



文字結合は、RDBMSによる仕様差が目立つ部分です。
SQL Serverでは、文字連結を「+」で行うという独自仕様になっています。
標準SQLでは「||」であり、多くのRDBMSで実装されています。DB2では「||」も使えま
すが、IBMのRDBMS間の互換性を優先するなら、「月 concat 日」という使い方を
推奨しているようです。
ともこ
大ベテラン
会議室デビュー日: 2007/09/14
投稿数: 111
投稿日時: 2008-02-25 22:30
忠犬さん、ご回答ありがとうございます。

2008-02-23 19:06--------------
[or 月='xx'」を、「or 月>='xx' and 月<='xx'」という条件式にしておけばいいのでは?
------------------------------
確かに!!ほんと盲点でした^^;

2008-02-23 19:06--------------
「||」、「月 concat 日」
------------------------------
忠犬さんって、ほんと知識が広いですねー!アドバイスを試してみます!
ありがとうございます!
1

スキルアップ/キャリアアップ(JOB@IT)