我有一张订单表
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
到,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会覆盖2015-07-18
而不是上的订单19 2015-07-19
。
我发现generate_series()
可以生成一个日期范围,但是我不知道如何将其与日期和订单ID结合使用。我的直觉是交叉连接,但在这种情况下我不知道如何进行这项工作。
谢谢
UPDATE 添加了一个sql小提琴。
2
您可以显示一些示例数据吗?第一次读取后,此活动/非活动和临时的事情不是很清楚。
—
dezso 2015年
是的,还不清楚。您的查询将为每个客户找到一个订单,这似乎不是确定性的。如果同一类型的客户端有2个或更多订单,则返回的两个订单中的哪一个将是任意的,并随每次执行而变化。因此,您在表上有一些未曾告诉我们的约束,或者您的查询不正确。
—
ypercubeᵀᴹ
我用更多详细信息更新了我的问题,是的,数据存在约束。
—
reconbot