4

Postgresql の個別のフィールドに年、月、日を含むテーブルを所有していますが、これらのフィールドの「間」を使用してクエリを作成する必要があります。私はいくつかのクレイジーなことを試しましたが、何もうまくいきませんでした...誰かが私を助けてくれますか?

例の表:

CREATE TABLE my_table
(
  id serial NOT NULL,
  day integer NOT NULL,
  month integer NOT NULL,
  year integer NOT NULL,
)
4

4 に答える 4

7

ダークサイドの助け

設計に行き詰まっていますが、これはこれまでに提案されたどのソリューションよりもシンプルで高速である必要があります: ad-hoc row types :

SELECT *
FROM   tbl
WHERE  (year, month, day) BETWEEN (2013,7,3)
                          AND     (2013,7,5);

ここでdb<>fiddle
古いsqlfiddle

適切な解決策

しかし、実際には、最初から適切なテーブル デザインを使用する必要があります。date日付を 3integer列ではなく として保存します。これにより、担保利益として有効な日付が強制されます。

CREATE TABLE tbl (
  tbl_id  serial PRIMARY KEY
, thedate date NOT NULL
);

thedate、の 3 つの列すべてが含まれday、のように 4 バイトが必要です。monthyearinteger

次に、タスクは簡単です。
日、月、年、または任意の形式の任意のサブユニットを取得するにはto_char()、 、extract()、またはを使用しますdate_trunc()。これらの関数は非常に高速で用途が広いです。

現在のテーブルとまったく同じようにVIEW見えるを作成できます。

CREATE view old_table AS
SELECT tbl_id
     , EXTRACT(day   FROM thedate)::int AS day
     , EXTRACT(month FROM thedate)::int AS month
     , EXTRACT(year  FROM thedate)::int AS year
FROM   my_table;

ソースが小さいため、少なくともテーブルと同じくらい高速です。

于 2013-07-16T21:55:21.160 に答える
2

適切な日付を使用するようにテーブル構造を変更できない場合は、次のように比較のためにフィールドから日付を作成できます。

SELECT *
FROM Table
WHERE to_date(Year||' '||Day||' '||Month, 'YYYY DD MM') BETWEEN date1 AND date2

それらがすべて整数の場合、それぞれを文字列に変換する必要があります。::VARCHAR()動作すると思います。またはCAST():

SELECT *
FROM Table
WHERE to_date(Year::varchar(4)||' '||Day::varchar(2)||' '||Month::varchar(2), 'YYYY DD MM') BETWEEN date1 AND date2
于 2013-07-16T21:21:16.233 に答える
2
WHERE
  (
       ((day >= :first_day) AND (month  = :first_month) AND (year  = :first_year))
    OR (                        (month >  :first_month) AND (year  = :first_year))
    OR (                                                    (year >  :first_year))
  )
  AND
  (
       ((day <= :final_day) AND (month  = :final_month) AND (year  = :final_year))
    OR (                        (month <  :final_month) AND (year  = :final_year))
    OR (                                                    (year <  :final_year))
  )

これは、インデックスシークの可能性を実際に破壊します。毎回テーブル全体をスキャンする可能性があります。

実際の日付フィールドを使用する方が、100 万倍も優れています。

上記のコードを公開したくはありません。ピアレビューをしても構いません。私は悔やまれるでしょう。

于 2013-07-16T21:21:48.437 に答える