给定一个包含时间段的表,查询每天的总和列表

时间:2014-03-26 16:24:15

标签: mysql sql oracle

让我们说我有一张表,说明两个日期之间有多少项有效。 此外,可能有多个这样的时期。

例如,给出一个表:

itemtype  | count | start       | end
A         | 10    | 2014-01-01  | 2014-01-10
A         | 10    | 2014-01-05  | 2014-01-08

这意味着有10件A型有效2014-01-01 - 2014-01-10,另外,有10件有效2014-01-05 - 2014-01-08。 例如,2014-01-06的有效项目总和为20。 如何查询表格以获得每日总和?我想要一个结果,如

2014-01-01  10
2014-01-02  10
2014-01-03  10
2014-01-04  10
2014-01-05  20
2014-01-06  20
2014-01-07  20
2014-01-08  20
2014-01-09  10
2014-01-10  10

可以用SQL完成吗?无论是Oracle还是MySQL都没问题

2 个答案:

答案 0 :(得分:1)

您正在寻找的基本语法如下:

在下面的示例中,我定义了一个名为DateTimePeriods的新表,其中包含StartDateEndDate列,这两列都是DATE列。< / p>

SELECT 
    SUM(NumericColumnName)
    , DateTimePeriods.StartDate
    , DateTimePeriods.EndDate
FROM 
    TableName
    INNER JOIN DateTimePeriods ON TableName.dateColumnName BETWEEN DateTimePeriods.StartDate and DateTimePeriods.EndDate
GROUP BY 
    DateTimePeriods.StartDate
    , DateTimePeriods.EndDate

显然上面的代码不会对你的数据库起作用,但应该给你一个合理的起点。您应该查看GROUP BYAggregate Functions。我也不确定每种数据库类型的通用BETWEEN是多少,但您可以使用<=>=之类的其他比较来做到这一点。

答案 1 :(得分:0)

有几种方法可以解决这个问题。首先,您需要一个要查询的密集日期列表。使用行生成器语句可以提供:

select date '2014-01-01' + level -1 d 
from dual 
connect by level <= 15;

然后,对于每个日期,选择库存总和:

with 
  sample_data as
    (select 'A' itemtype, 10 item_count, date '2014-01-01' start_date, date '2014-01-10' end_date from dual union all
     select 'A', 10, date '2014-01-05', date '2014-01-08' from dual),
  periods as (select date '2014-01-01' + level -1 d from dual connect by level <= 15)
select 
  periods.d,
  (select sum(item_count) from sample_data where periods.d between start_date and end_date) available
from periods
where periods.d = date '2014-01-06';

您需要动态设置要生成的日期行数。

如果您只需要一行,那么像这样的查询就可以了:

with 
  sample_data as
    (select 'A' itemtype, 10 item_count, date '2014-01-01' start_date, date '2014-01-10' end_date from dual union all
     select 'A', 10, date '2014-01-05', date '2014-01-08' from dual)
select sum(item_count)
from sample_data
where date '2014-01-06' between start_date and end_date;