0

我在执行典型的报表样式 SQL 时遇到了一些问题,希望有更多经验的人能够提供帮助。

我有以下表格

产品

  • product_id
  • 产品名称
  • 产品分类

产品缺陷

  • product_id
  • 缺陷日期
  • 高优先级
  • med_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

…</p>

到目前为止我所做的是:

  • 创建一个名为 calendar 的查找表,其中包含一系列日期,可以向后/向前几年
  • 右加入查找/产品缺陷表以获取一系列日期,因此可以将缺失的天数标记为 0
  • 使用 COALESCE 和 SUM 计算总计并将任何缺失的数据更改为 0
  • 在 defect_date 上使用 MIN / MAX 来获得准确的报告范围

这几天我一直在努力解决这个问题,希望有人能提供帮助。

谢谢

4

4 回答 4

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

(注意:这是未经测试的,所以可能有语法错误。)

于 2013-01-15T15:37:43.223 回答
1

像这样的东西。我使用双而不是日历,您可以使用或替换日历表。

例如,开始日期为 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;
于 2013-01-15T15:44:11.247 回答
1

因此,这使用子工厂查询子句 ( 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 
于 2013-01-15T15:44:57.093 回答
0

仅日历表示例。将月数从 -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...

于 2013-01-15T16:23:40.243 回答