日付を保持するテーブルを持つ PostgreSQL データベースがあります。ここで、すべての年にわたって (日/月)15/02
までの日付範囲内のすべての行を検索する必要があります。21/06
結果の例:
1840-02-28
1990-06-21
1991-02-15
1991-04-25
1992-05-30
1995-03-04
1995-04-10
2001-02-03
2010-04-06
日付を保持するテーブルを持つ PostgreSQL データベースがあります。ここで、すべての年にわたって (日/月)15/02
までの日付範囲内のすべての行を検索する必要があります。21/06
結果の例:
1840-02-28
1990-06-21
1991-02-15
1991-04-25
1992-05-30
1995-03-04
1995-04-10
2001-02-03
2010-04-06
年に関係なく、特定の日の間の日付が必要であると仮定すると (誕生日カードなどを送信する場合など)、次のようにテストを設定できます。
CREATE TABLE d (dt date);
COPY d FROM STDIN;
1840-02-28
1990-06-21
1991-02-15
1991-04-25
1992-05-30
1995-03-04
1995-04-10
2001-02-03
2010-04-06
\.
また、「行値コンストラクター」を使用して、目的の範囲を簡単に選択できます。
SELECT * FROM d
WHERE (EXTRACT(MONTH FROM dt), EXTRACT(DAY FROM dt))
BETWEEN (2, 15) AND (6, 21);
どちらが得られますか:
dt ------------ 1840-02-28 1990-06-21 1991-02-15 1991-04-25 1992-05-30 1995-03-04 1995-04-10 2010-04-06 (8行)
次の構文を使用できます。
SELECT * FROM tableName WHERE dateColumnName BETWEEN '2012.01.01' AND '2012.08.14';
以下を置き換えるだけです。
tableName - Name of the table you are going to access
dateColumnName - Name of the column whch contains dates
2012.08.1 - Start date
2012.08.21 - End date
2つの日付を入力するときは、上記の例を注意深く調べてください。同じ形式で入力し、sで囲みます''
。
マークを列名に置き換える*
と、その列の値のみを除外できます。
お役に立てば幸いです。
@kgrittnの質問の解釈は正確であり、行コンストラクターのエレガントな使用が大好きです。いくつかの代替案をテストした後はなおさらですが、どれもパフォーマンスに匹敵するものはありませんでした:
65426 行の実際のテーブルでテスト済み。32107認定。PostgreSQL 9.1.4、ベスト オブ ファイブEXPLAIN ANALYZE
:
SELECT * FROM tbl
WHERE to_char(data, 'MMDD') BETWEEN '0215' AND '0621';
合計実行時間: 251.188 ミリ秒
SELECT * FROM tbl
WHERE to_char(data, 'MMDD')::int BETWEEN 215 AND 621;
総実行時間: 250.965 ミリ秒
SELECT * FROM tbl
WHERE to_char(data, 'MMDD') COLLATE "C" BETWEEN '0215' AND '0621';
総実行時間: 221.732 ミリ秒
文字列の比較は、「非ロケール」を使用した方が高速です。C
詳細については、照合サポートに関するマニュアルを参照してください。
SELECT * FROM tbl
WHERE EXTRACT(MONTH FROM data)*100 + EXTRACT(DAY FROM data)
BETWEEN 215 AND 621;
合計実行時間: 209.965 ミリ秒
SELECT * FROM tbl
WHERE EXTRACT(MONTH FROM data) BETWEEN 3 AND 5
OR EXTRACT(MONTH FROM data) = 2 AND EXTRACT(DAY FROM data) >= 15
OR EXTRACT(MONTH FROM data) = 6 AND EXTRACT(DAY FROM data) <= 21;
総実行時間: 160.169 ミリ秒
SELECT * FROM tbl
WHERE EXTRACT(MONTH FROM data) BETWEEN 2 AND 6
AND CASE EXTRACT(MONTH FROM data)
WHEN 2 THEN EXTRACT(DAY FROM data) >= 15
WHEN 6 THEN EXTRACT(DAY FROM data) <=21
ELSE TRUE END;
総実行時間: 147.390 ミリ秒
SELECT * FROM tbl
WHERE CASE EXTRACT(MONTH FROM data)
WHEN 3 THEN TRUE
WHEN 4 THEN TRUE
WHEN 5 THEN TRUE
WHEN 2 THEN EXTRACT(DAY FROM data) >= 15
WHEN 6 THEN EXTRACT(DAY FROM data) <= 21
ELSE FALSE END;
総実行時間: 131.907 ミリ秒
行コンストラクターを使用した@Kevinのソリューション:
SELECT * FROM tbl
WHERE (EXTRACT(MONTH FROM data), EXTRACT(DAY FROM data))
BETWEEN (2, 15) AND (6, 21);
総実行時間: 125.460 ミリ
秒
それを打ち負かす唯一の方法は、インデックスを使用することです。上記のクエリはいずれも、 でプレーン インデックスを使用できませんdata
。ただし、読み取りパフォーマンスが重要な場合 (および書き込みパフォーマンスにわずかなコストがかかる場合) は、関数インデックスに頼ることができます。
CREATE INDEX ON tbl(EXTRACT(MONTH FROM data), EXTRACT(DAY FROM data));
SELECT * FROM tbl
WHERE (EXTRACT(MONTH FROM data), EXTRACT(DAY FROM data))
BETWEEN (2, 15) AND (6, 21);
総実行時間: 85.895 ミリ秒
ここで、Kevin のクエリにやっと勝てます。彼の場合に必要な複数列のインデックスではなく、1 つの列のインデックスを使用することです。
CREATE INDEX ON tbl(
CAST(EXTRACT(MONTH FROM data) * 100 + EXTRACT(DAY FROM data) AS int));
SELECT * FROM tbl
WHERE (EXTRACT(MONTH FROM data) * 100 + EXTRACT(DAY FROM data))::int
BETWEEN 215 AND 621;
総実行時間: 84.215 ミリ秒
単純な条件 >= および <= または同様の条件を使用するか、 between/and を使用できますが、正確なデータ型を知ることが秘訣です。日付フィールドに時間が含まれている場合があり、クエリがうまくいかない可能性があるため、日付関連の関数を使用して時間の問題を取り除くことをお勧めします。SQL Server では、これを行う一般的な関数は datediff 関数です。
WHERE
演算子で句を使用しBETWEEN
ます。見る:
http://www.postgresql.org/docs/current/static/functions-comparison.html#FUNCTIONS-COMPARISON
と:
http://www.postgresql.org/docs/current/static/sql-select.html http://www.postgresql.org/docs/current/static/tutorial.html
それでも問題が解決しない場合は、次のように質問を拡張してください。
\d tablename
psql のコマンドまたは元のCREATE TABLE
ステートメントのいずれかから、作業しているテーブルの構造。