注文表があります
Column | Type | Modifiers
------------+-----------------------------+-----------------------------------------------------
id | integer | not null default nextval('orders_id_seq'::regclass)
client_id | integer | not null
start_date | date | not null
end_date | date |
order_type | character varying | not null
データにはclient_idの重複しない永続的な注文があり、時にはclient_idが一致する場合、start_dateの永続的な注文を上書きする一時的な注文があります。同じタイプの注文が重複しないようにするアプリケーションレベルの制約があります。
id | client_id | start_date | end_date | order_type
----+-----------+------------+------------+------------
17 | 11 | 2014-02-05 | | standing
18 | 15 | 2014-07-16 | 2015-07-19 | standing
19 | 16 | 2015-04-01 | | standing
20 | 16 | 2015-07-18 | 2015-07-18 | temporary
たとえば、2015-07-18
クライアント16では、注文#20がアクティブな注文であるため、注文#19を上書きします。いくつかの大騒ぎで、日付のアクティブな注文IDを照会する効率的な方法を見つけました。
SELECT id from (
SELECT
id,
first_value(id) OVER (PARTITION BY client_id ORDER BY order_type DESC) active_order_id
FROM orders
WHERE start_date <= ? and (end_date is null OR end_date >= ?)
) active_orders
WHERE id = active_order_id
これを2015-07-18
プレースホルダーとしてクエリすると、次のようになります。
id
----
17
18
20
このクエリのクエリプランは、他のいくつかのアイデア(ある日付のクライアントの一時注文の数をカウントするサブクエリなど)と比較すると非常に小さく、かなり満足しています。(テーブルのデザイン、私は興奮していません)
今、私はそれらがアクティブな日付と結合された日付範囲のすべてのアクティブな注文を見つける必要があります。たとえば、日付範囲が2015-07-18
toの2015-07-19
場合、次の結果が必要です。
active_date | id
------------+----
2015-07-18 | 17
2015-07-18 | 18
2015-07-18 | 20
2015-07-19 | 17
2015-07-19 | 18
2015-07-19 | 19
注文20は注文19をオーバーライドします2015-07-18
が、オンではありません2015-07-19
。
generate_series()
日付の範囲を生成できることがわかりましたが、日付と注文IDのテーブルを取得するためにこれをどのように結合するのかわかりません。私の直感はクロスジョインですが、この状況でそれを機能させる方法を理解できません。
ありがとう
UPDATE SQLフィドルが 追加されました。