207

Postgres サーバーに次のデータベース テーブルがあります。

id      date          Product Sales
1245    01/04/2013    Toys    1000     
1245    01/04/2013    Toys    2000
1231    01/02/2013    Bicycle 50000
456461  01/01/2014    Bananas 4546

SUM次のように、Sales列の結果を月と年でグループ化するクエリを作成したいと思います。

Apr    2013    3000     Toys
Feb    2013    50000    Bicycle
Jan    2014    4546     Bananas

それを行う簡単な方法はありますか?

4

7 に答える 7

387

受け入れられた回答に非常に多くの賛成票があるとは信じられません。これは恐ろしい方法です。

date_truncを使用した正しい方法は次のとおりです。

   SELECT date_trunc('month', txn_date) AS txn_month, sum(amount) as monthly_sum
     FROM yourtable
 GROUP BY txn_month

それは悪い習慣ですが、使用すると許されるかもしれません

 GROUP BY 1

非常に単純なクエリで。

使用することもできます

 GROUP BY date_trunc('month', txn_date)

日付を選択したくない場合。

于 2014-11-18T18:14:00.690 に答える
252
select to_char(date,'Mon') as mon,
       extract(year from date) as yyyy,
       sum("Sales") as "Sales"
from yourtable
group by 1,2

Radu の要求に応じて、そのクエリについて説明します。

to_char(date,'Mon') as mon,: 「日付」属性を月の短い形式の定義済みフォーマットに変換します。

extract(year from date) as yyyy: Postgresql の "extract" 関数を使用して、"date" 属性から YYYY 年を抽出します。

sum("Sales") as "Sales"注: SUM() 関数は、すべての「Sales」値を合計し、大文字と小文字を区別するエイリアスを提供します。大文字と小文字の区別は、二重引用符を使用して維持されます。

group by 1,2: GROUP BY 関数には、集計の一部ではない SELECT リストのすべての列が含まれている必要があります (別名、SUM/AVG/MIN/MAX などの関数内にないすべての列)。これにより、列の一意の組み合わせ (この場合は月と年の列) ごとに SUM() を適用する必要があることがクエリに伝えられます。"1,2" の部分は、列のエイリアスを使用する代わりに簡略化されていますが、読みやすくするために完全な "to_char(...)" および "extract(...)" 式を使用するのがおそらく最善です。

于 2013-07-05T15:26:58.663 に答える
49

to_char実際に、年と月を一気に引き出すことができます。

select to_char(date('2014-05-10'),'Mon-YY') as year_month; --'May-14'
select to_char(date('2014-05-10'),'YYYY-MM') as year_month; --'2014-05'

または上記のユーザーの例の場合:

select to_char(date,'YY-Mon') as year_month
       sum("Sales") as "Sales"
from some_table
group by 1;
于 2014-10-03T20:02:20.243 に答える
7

postgres の date_part() 関数を使用して結果を得る別の方法があります。

 SELECT date_part('month', txn_date) AS txn_month, date_part('year', txn_date) AS txn_year, sum(amount) as monthly_sum
     FROM yourtable
 GROUP BY date_part('month', txn_date)

ありがとう

于 2018-04-11T07:11:45.623 に答える
0

Postgres にはいくつかの種類のタイムスタンプがあります。

タイムゾーンなしのタイムスタンプ- (UTC タイムスタンプを保存することをお勧めします) 多国籍データベース ストレージにあります。この場合、クライアントは各国のタイムゾーン オフセットを処理します。

タイムゾーン付きタイムスタンプ- タイムゾーン オフセットはすでにタイムスタンプに含まれています。

場合によっては、データベースがタイムゾーンを使用していなくても、ローカル タイムゾーンと夏時間に関してレコードをグループ化する必要があります (例: https://www.timeanddate.com/time/zone/romania/bucharest ) 。

タイムゾーンを追加するには、この例を使用して、タイムゾーン オフセットを自分のものに置き換えます。

"your_date_column" at time zone '+03'

DST に固有の +1 サマータイム オフセットを追加するには、タイムスタンプが夏 DST に該当するかどうかを確認する必要があります。これらの間隔は 1 日または 2 日で変化するため、月末の記録に影響を与えない近似を使用するため、この場合、毎年の正確な間隔を無視できます。

より正確なクエリを作成する必要がある場合は、条件を追加してさらにケースを作成する必要があります。しかし、大まかに言えば、データベースでタイムゾーンのないタイムスタンプを見つけた場合、タイムゾーンとサマータイムに関して月ごとにデータを分割する場合、これはうまく機能します。

SELECT 
    "id", "Product", "Sale",
    date_trunc('month', 
        CASE WHEN 
            Extract(month from t."date") > 03 AND
            Extract(day from t."date") > 26 AND
            Extract(hour from t."date") > 3 AND
            Extract(month from t."date") < 10 AND
            Extract(day from t."date") < 29 AND
            Extract(hour from t."date") < 4
        THEN 
            t."date" at time zone '+03' -- Romania TimeZone offset + DST
        ELSE
            t."date" at time zone '+02' -- Romania TimeZone offset 
        END) as "date"
FROM 
    public."Table" AS t
WHERE 1=1
    AND t."date" >= '01/07/2015 00:00:00'::TIMESTAMP WITHOUT TIME ZONE
    AND t."date" < '01/07/2017 00:00:00'::TIMESTAMP WITHOUT TIME ZONE
GROUP BY date_trunc('month', 
    CASE WHEN 
        Extract(month from t."date") > 03 AND
        Extract(day from t."date") > 26 AND
        Extract(hour from t."date") > 3 AND
        Extract(month from t."date") < 10 AND
        Extract(day from t."date") < 29 AND
        Extract(hour from t."date") < 4
    THEN 
        t."date" at time zone '+03' -- Romania TimeZone offset + DST
    ELSE
        t."date" at time zone '+02' -- Romania TimeZone offset 
    END)
于 2017-07-17T16:29:58.573 に答える