[英]SQL query for finding finished records published for different time periods
[英]SQL Query building: howto decompose periods of time in different rows
如何构建SQL查询来分解某些时期,例如几个月。
数据库表:
id fromdate todate value
--------------------------------------------
100 01.01.2015 01.03.2015 10
所需的查询结果:
id fromdate todate value
--------------------------------------------
100 01.01.2015 01.02.2015 5,25
100 01.02.2015 01.03.2015 4,75
其中值基于两个日期之间的天数,例如:
value(january) = 31(january nr of days) * 10(original value) / 59(total days) = 5,25
谢谢
对于这样的计算,您可以使用date dimension
-一个表格,其中将您网域中的所有日期都包含为单行( 例如,请参见)。
在数据库中有了日期维度后,事情就变得简单了:
WITH data_by_date AS
( -- Here we join dates to your periods to turn each row in
-- as many rows as there are days in the period.
-- We also turn value field into value_per_day.
SELECT
d.date,
d.month_year,
t.id,
value / (t.todate - t.fromdate) as value_per_day
FROM
dim_date d INNER JOIN
my_table t ON d.date >= t.fromdate AND d.date < t.todate
)
SELECT -- Here we group by results by month.
dd.id,
MIN(dd.date) as fromdate,
MAX(dd.date) as todate,
SUM(dd.value_per_day) as value
FROM data_by_date dd
GROUP BY dd.id, dd.month_year
使用分层查询为每个条目生成月份列表:
Oracle 11g R2架构设置 :
CREATE TABLE TEST (id, fromdate, todate, value ) AS
SELECT 100, DATE '2015-01-01', DATE '2015-03-01', 10 FROM DUAL
UNION ALL SELECT 200, DATE '2014-12-22', DATE '2015-01-06', 30 FROM DUAL
查询1 :
SELECT ID,
fromdate,
todate,
VALUE * ( todate - fromdate ) / ( maxdate - mindate ) AS value
FROM (
SELECT ID,
GREATEST( t.fromdate, m.COLUMN_VALUE ) AS fromdate,
LEAST( t.todate, ADD_MONTHS( m.COLUMN_VALUE, 1 ) ) AS todate,
t.fromdate AS mindate,
t.todate AS maxdate,
t.value
FROM TEST t,
TABLE(
CAST(
MULTISET(
SELECT ADD_MONTHS( TRUNC( t.fromdate, 'MM' ), LEVEL - 1 )
FROM DUAL
CONNECT BY
ADD_MONTHS( TRUNC( t.fromdate, 'MM' ), LEVEL - 1 ) < t.todate
)
AS SYS.ODCIDATELIST
)
) m
)
结果 :
| ID | FROMDATE | TODATE | VALUE |
|-----|----------------------------|----------------------------|-------------------|
| 100 | January, 01 2015 00:00:00 | February, 01 2015 00:00:00 | 5.254237288135593 |
| 100 | February, 01 2015 00:00:00 | March, 01 2015 00:00:00 | 4.745762711864407 |
| 200 | December, 22 2014 00:00:00 | January, 01 2015 00:00:00 | 20 |
| 200 | January, 01 2015 00:00:00 | January, 06 2015 00:00:00 | 10 |
使用函数add_months()
和分层子查询为每个id生成句点:
select id, d1, d2, round(value*(d2-d1)/nod, 2) value
from (
select id, value, todate-fromdate nod, add_months(fromdate, level-1) d1,
least(add_months(fromdate, level), todate) d2
from data
connect by add_months(fromdate, level) <= trunc(add_months(todate, 1)-1)
and id = prior id and prior dbms_random.value is not null )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.