6

日付を保持するテーブルを持つ 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
4

5 に答える 5

7

年に関係なく、特定の日の間の日付が必要であると仮定すると (誕生日カードなどを送信する場合など)、次のようにテストを設定できます。

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行)
于 2012-08-15T12:59:02.127 に答える
1

次の構文を使用できます。

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で囲みます''

マークを列名に置き換える*と、その列の値のみを除外できます。

お役に立てば幸いです。

于 2012-08-14T04:52:41.650 に答える
1

@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 ミリ秒

于 2012-08-18T23:32:42.903 に答える
1

単純な条件 >= および <= または同様の条件を使用するか、 between/and を使用できますが、正確なデータ型を知ることが秘訣です。日付フィールドに時間が含まれている場合があり、クエリがうまくいかない可能性があるため、日付関連の関数を使用して時間の問題を取り除くことをお勧めします。SQL Server では、これを行う一般的な関数は datediff 関数です。

于 2013-11-21T12:20:40.087 に答える
1

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 tablenamepsql のコマンドまたは元のCREATE TABLEステートメントのいずれかから、作業しているテーブルの構造。
  • 一部サンプル内容
  • 問題が発生しているクエリ
  • 予想された結果
于 2012-08-14T03:58:21.823 に答える