基本的な解決策
月の完全なリストを生成し、LEFT JOIN
残りの部分:
SELECT *
FROM (
SELECT to_char(m, 'YYYY-MON') AS yyyymmm
FROM generate_series(<start_date>, <end_date>, interval '1 month') m
) m
LEFT JOIN ( <your query here> ) q USING (yyyymmm);
詳細な説明付きの関連回答:
ケースの高度なソリューション
あなたの質問は私が最初に理解したよりも複雑です。 すべての現在の合計が必要です 選択したアイテムの行の場合、最小日付より古い行をトリミングし、不足している月に前月の事前計算された合計を入力します。
私は今、LEFT JOIN LATERAL
でこれを達成しています 。
SELECT COALESCE(m.yearmonth, c.yearmonth)::date, sold_qty, on_hand
FROM (
SELECT yearmonth
, COALESCE(sold_qty, 0) AS sold_qty
, sum(on_hand_mon) OVER (ORDER BY yearmonth) AS on_hand
, lead(yearmonth) OVER (ORDER BY yearmonth)
- interval '1 month' AS nextmonth
FROM (
SELECT date_trunc('month', c.change_date) AS yearmonth
, sum(c.sold_qty / s.qty)::numeric(18,2) AS sold_qty
, sum(c.on_hand) AS on_hand_mon
FROM item_change c
LEFT JOIN item i USING (item_id)
LEFT JOIN item_size s ON s.item_id = i.item_id AND s.name = i.sell_size
LEFT JOIN item_plu p ON p.item_id = i.item_id AND p.seq_num = 0
WHERE c.change_date < date_trunc('month', now()) - interval '1 day'
AND c.item_id = (SELECT item_id FROM item_plu WHERE number = '51515')
GROUP BY 1
) sub
) c
LEFT JOIN LATERAL generate_series(c.yearmonth
, c.nextmonth
, interval '1 month') m(yearmonth) ON TRUE
WHERE c.yearmonth > date_trunc('year', now()) - interval '540 days'
ORDER BY COALESCE(m.yearmonth, c.yearmonth);
SQLフィドル 最小限のテストケースで。
主なポイント:
-
クエリからVIEWを完全に削除しました。利益がないために多くの費用がかかります。
-
シングルを選択したため
item_id
、GROUP BY item_id
を実行する必要はありません またはPARTITION BY item_id
。 -
短いテーブルエイリアスを使用し、すべての参照を明確にします。特に、公開フォーラムに投稿する場合はそうです。
-
結合の括弧は単なるノイズでした。結合は、デフォルトで左から右に実行されます。
-
簡略化された日付境界(タイムスタンプで操作するため):
date_trunc('year', current_date) - interval '540 days' date_trunc('month', current_date) - interval '1 day'
同等ですが、以下よりも単純で高速です:
current_date - date_part('day',current_date)::integer - 540 current_date - date_part('day',current_date)::integer -
すべての計算の後に不足している月を
generate_series()
で埋めるようになりました 行ごとの呼び出し。 -
LEFT JOIN LATERAL ... ON TRUE
である必要があります 、JOIN LATERAL
の短縮形ではありません 最後の列のコーナーケースをキャッチします。詳細な説明:
重要な注意事項:
character(22)
ひどい 主キー(または任意)のデータ型 桁)。詳細:
理想的には、これはint
になります またはbigint
列、または場合によっては UUID
。
また、金額をmoney
タイプまたはinteger
(セントを表す)全体的にはるかに優れたパフォーマンスを発揮します。
長期的には 、計算の最初からすべての行を含める必要があるため、パフォーマンスは低下する可能性があります。古い行を切り取り、on_hold
のバランスを具体化する必要があります 毎年か何かで。