2016-06-07 35 views
3

我有运送燃料的表如下:如何按日期顺序选择总数达到任意数量的记录?

Date  Time  Qty 
20160101 0800  4500 
20160203 0900  6000 
20160301 0810  3400 
20160328 1710  5300 
20160402 1201  6000 

我知道,在4月1日我在坦克有万升所以现在我要选择只是弥补了总的交付。这意味着我需要20160328,20160301和20160203的记录。我正在使用Postgres,我想知道如何构建将完成此任务的选择语句。 我明白如何使用where子句过滤日期少于4月1日的记录,但我不知道如何指示Postgres以相反的日期顺序选择记录,直到所选数量大于或等于10,000。

+0

这被称为RELA该部门https://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/ –

回答

0

您可以创建一个使用基于降序的日期和时间的顺序,像这样的窗口函数运行总计:

SELECT 
    Date, 
    Time, 
    Qty 
FROM 
(
SELECT 
    Date, 
    Time, 
    Qty, 
    SUM(Qty) OVER (ORDER BY Date DESC, Time DESC) AS Running_Total 
FROM 
    fuel_deliveries 
WHERE 
    Date < '20160402' 
) rt 
WHERE 
    Running_Total <= 10000; 

内/子查询让你运行总计,但之后要过滤在其上,该值为小于或等于10000。

+0

这是一个开始,但不幸的是,这不会选择第三个纪录因为运行总数超过10,000。一旦总数达到10,000或更多,我需要停下来。其次,当fuel_deliveries表保存多年的数据时,内部SQL将在现实生活中汇总数百万条记录。我希望能够提高它的效率,因此只需要总计记录直到总数超过10,000。 –

+0

也许我不明白,但除非恰好是这样的总和,否则你不会让它“完全停止”在10,000。它要么会导致超过10000或更少 - 不可能完全是这样。 – Nicarus

+0

是的,它不太可能会停在正好10,000的位置,所以我希望它在等于或超过10,000的第一个记录上停下来,因此我知道所有可能的交付都构成了10,000。 –

1
with d as (
    select *, sum(qty) over (order by date desc, time desc) as total 
    from delivery 
    where date between '20160101' and '20160401' 
) 
select * 
from d 
where total < 10000 
union 
(
    select * 
    from d 
    where total >= 10000 
    order by date desc, time desc 
    limit 1 
) 
order by date desc, time desc 
; 
    date | time | qty | total 
------------+----------+------+------- 
2016-03-28 | 17:10:00 | 5300 | 5300 
2016-03-01 | 08:10:00 | 3400 | 8700 
2016-02-03 | 09:00:00 | 6000 | 14700 

数据:

create table delivery (date date, time time, qty int); 
insert into delivery (date, time, qty) values 
('20160101','0800',4500), 
('20160203','0900',6000), 
('20160301','0810',3400), 
('20160328','1710',5300), 
('20160402','1201',6000); 
+0

谢谢你,这工作正常。唯一的问题是决定如何使“与”更高效,因此我不累计多年的数据。 –

+0

@SimonWhite:只要将它限制在where子句中的合理时间范围内。 –

+0

@SimonWhite:包含日期限制并修复了一个错误 –