日期范围报告 - 聚合
Posted
技术标签:
【中文标题】日期范围报告 - 聚合【英文标题】:Date Range Report - Aggregation 【发布时间】:2013-01-15 15:32:17 【问题描述】:我在执行典型的报表样式 SQL 时遇到了一些问题,希望有更多经验的人能够提供帮助。
我有以下表格
产品
product_id 产品名称 product_categoryproduct_defects
product_id 缺陷日期 high_priority med_priority low_priority日历
日期我想要的是能够生成一份报告,其中概述了每天与每个产品类别相关的高/中/低缺陷的数量,例如,即使 product_defect 中可能不存在特定日期的数据,在在这种情况下,它应该返回为 0。示例:
产品类别 |日期 |高 |中 |低
1 2012-10-01 1 5 6
2 2012-10-01 2 4 3
3 2012-10-01 1 5 6
1 2012-10-02 0 0 0
2 2012-10-02 2 4 3
3 2012-10-02 1 5 6
…
到目前为止我所做的是:
创建一个名为 calendar 的查找表,其中包含一系列日期,可以向后/向前几年 右加入 lookup/product_defects 表以获取一系列日期,因此可以将缺失的天数标记为 0 使用 COALESCE 和 SUM 计算总计并将任何缺失的数据更改为 0 使用defect_date 的MIN / MAX 来获取准确的报告范围这几天我一直在纠结这个问题,希望有人能提供帮助。
谢谢
【问题讨论】:
是否有理由为每个优先级设置一列?这似乎违反了规范化规则。看起来您的表本身正在存储一个聚合。 【参考方案1】:你需要从产品和日期的所有组合开始,然后加入缺陷:
select p.product_category, c.date,
coalesce(SUM(high_priority), 0) as high_priority,
coalesce(SUM(med_priority), 0) as med_priority,
coalesce(SUM(low_priority), 0) as low_priority
from product p cross join
calendar c left outer join
product_defects pd
on pd.product_id = p.product_id and
pd.date = c.date
group by p.product_category, c.date
order by 2, 1
(注意:这是未经测试的,所以可能有语法错误。)
【讨论】:
谢谢您,先生 - 这非常有效。我唯一需要添加的是: WHERE (c.date BETWEEN (SELECT MIN(date) FROM product_defects) AND (SELECT MAX(date) FROM product_defects))【参考方案2】:类似的东西。我使用双而不是日历,您可以使用或替换日历表。
例如,开始日期为 2013 年 1 月 1 日至 2013 年 1 月 15 日。
with dates as (select to_date('01/01/2013', 'dd/mm/yyyy') + rownum - 1 dte
from dual
connect by level <= to_date('15/01/2013', 'dd/mm/yyyy')
- to_date('01/01/2013', 'dd/mm/yyyy') + 1)
select dt.dte, p.product_id, p.product_name,
sum(d.high_priority), sum(d.med_priority), sum(d.low_priority)
from products p
inner join product_defects d
on d.product_id = p.product_id
right outer join dates dt
on dt.dte = d.defect_date -- trunc(d.defect_date) if you store with a time element.
group by dt.dte, p.product_id, p.product_name
order by dt.dte;
【讨论】:
【参考方案3】:因此,这使用子工厂查询子句 (cte
) 来汇总每天每个类别的所有缺陷。我使用这个结构来使逻辑更清晰;还有其他方法可以做到这一点。然后将子查询外连接到日历表。
with cte as
( select p.product_category
, d.defect_date
, sum(pd.high_priority) as high_priority
, sum(pd.med_priority) as med_priority
, sum(pd.low_priority) as low_priority
from product p
join product_defect pd
on (pd.product_id = p.product_id )
group by p.product_category
, d.defect_date )
select cte.product_category
, cal.date
, nvl(cte.high_priority, 0) as high_priority
, nvl(cte.med_priority, 0) as med_priority
, nvl(cte.low_priority, 0) as low_priority
from calendar cal
left outer join cte
on cal.date = cte.defect_date
order by cte.product_category
, cal.date
【讨论】:
【参考方案4】:仅限日历表示例。将月数从 -24(2 年)增加到任意数字 - 复制/粘贴代码:
-- 2 years back by date --
SELECT TRUNC(SYSDATE, 'YEAR') - LEVEL AS mydate
FROM dual
CONNECT BY LEVEL <= TRUNC(SYSDATE, 'yy') - TRUNC(Add_Months(SYSDATE, -24), 'yy')
/
添加更多日期:
-- 2 years back by date and week --
SELECT mydate
, TRUNC(mydate, 'iw') wk_starts
, TRUNC(mydate, 'iw') + 7 - 1/86400 wk_ends
, TO_NUMBER (TO_CHAR (mydate, 'IW')) ISO_wk#
FROM
(
SELECT TRUNC(SYSDATE, 'YEAR') - LEVEL AS mydate
FROM dual
CONNECT BY LEVEL <= TRUNC(SYSDATE, 'yy') - TRUNC(Add_Months(SYSDATE, -24), 'yy')
)
/
发布创建表并插入脚本以回答您的其余问题或使用 sqlfiddle...
【讨论】:
以上是关于日期范围报告 - 聚合的主要内容,如果未能解决你的问题,请参考以下文章
Elassandra / Elastic Search中的聚合,日期范围查询