这是PostgreSQL的语法,但它应该很容易转换为其它SQL方言
--Sample data
create table offdays(datum date);
insert into offdays(datum)
select to_date('2008-01-10','yyyy-MM-dd') UNION
select to_date('2008-01-11','yyyy-MM-dd') UNION
select to_date('2008-01-14','yyyy-MM-dd') UNION
select to_date('2008-01-20','yyyy-MM-dd') UNION
select to_date('2008-01-21','yyyy-MM-dd') UNION
select to_date('2008-01-26','yyyy-MM-dd');
create table leadtime (product_id integer , lead_time integer);
insert into leadtime(product_id,lead_time) values (9,5);
create table myorder (order_id integer,product_id integer, datum date);
insert into myorder(order_id,product_id,datum)
values (1,9,to_date('2008-01-09','yyyy-MM-dd'));
insert into myorder(order_id,product_id,datum)
values (2,9,to_date('2008-01-16','yyyy-MM-dd'));
insert into myorder(order_id,product_id,datum)
values (3,9,to_date('2008-01-23','yyyy-MM-dd'));
--Query
select order_id,min(finished_date)
FROM
(select mo.order_id,(mo.datum+lead_time+count(od2.*)::integer-1) as finished_date
from
myorder mo
join leadtime lt on (mo.product_id=lt.product_id)
join offdays od1 on (mo.datum<od1.datum)
left outer join offdays od2 on (mo.datum<od2.datum and od2.datum<od1.datum)
group by mo.order_id,mo.datum,lt.lead_time,od1.datum
having (mo.datum+lead_time+count(od2.*)::integer-1) < od1.datum) tmp
group by 1;
--Results :
1 2008.01.16
2 2008.01.22
这将不会返回结果为,将截止日期后在offdays表完成订单(订单3号),所以你必须小心按时插入星期五。假设订单不会在星期一开始。
不好意思,但这是我见过的最棘手的问题之一。您正在将日历与订单表交叉连接,其中日历上唯一的过滤器是两个布尔值,并且您有一个前导时间表,并加入了您加入order.LeadId的leadId。咦? – 2008-09-18 15:16:59
嗨达雷尔 - 是的,我刚刚意识到我错过了他提到的产品表。 Mea culpa! 我确实意识到日历交叉连接会使这个非常缓慢 - 我正试图考虑如何重写它...... – 2008-09-18 15:28:37