我获得了项目数据的观点,并被要求总结一个月内有多少项目正在开放。
PROJECT_ID OPEN_DATE CLOSE_DATE OWNER
1 8/01/2012 09/01/2012 JEFF
2 8/08/2012 10/01/2012 JEFF
3 9/01/2012 Null JEFF
4 9/12/2012 Null JEFF
5 9/24/2012 11/01/2012 JEFF
6 10/01/2012 12/01/2012 JEFF
7 10/09/2012 01/01/2013 JEFF
我需要像这样的OPEN计数。一旦我得到基本查询,我就需要按项目所有者过滤/分组
AUG12 SEPT12 OCT12 NOV12 DEC12 JAN13 FEB13
2 4 5 4 3 2 1
^ ^ ^ ^ ^ ^ ^
| | | | | | |-> From Projects 3 & 4
| | | | | |-> From Projects 3 & 4
| | | | |-> From Projects 3,4 & 7
| | | |-> From Projects 3,4,6 & 7
| | |-> From Projects 3,4,5,6 & 7
| |-> From Projects 2,3,4, & 5
|-> From Project 1 & 2
最新 这是我根据戈登的建议连接起来的。查询慢了4-5秒
SELECT SUM(case when (OPEN_DATE <= thedate and CLOSE_DATE > thedate) or (OPEN_DATE <= thedate and CLOSE_DATE Is Null) then 1 else 0 end) as Open
1. From (select * FROM Project
2. WHERE Project.Owner = :owner AND Project.action_for = :actionFor )
3. cross join ( select add_months(last_day(SYSDATE), level-7)
4. as thedate from dual connect by level <= 12 )
5. group by to_char(thedate, 'YYYY-MM') order by 1
除了慢,我不确定它是否与我的真实数据一起正常工作。我需要分解查询以给我结果,我可以手动检查结果。如何调试sql语句?我的意思是因为你得到结果你怎么知道他们是正确的?
答案 0 :(得分:1)
这是一种方法。它将值放在单独的行上,而不是放在单独的列中。无论如何,我发现更容易使用:
select owner, to_char(thedate, 'YYYY-MM') as YYYYMM,
SUM(case when open_date <= thedate and close_date > thedate then 1 else 0 end) as cnt
from project p cross join
(select to_date('2012-08-31', 'yyyy-mm-dd') as thedate from dual union all
select to_date('2012-09-30', 'yyyy-mm-dd') as thedate from dual union all
select to_date('2012-10-31', 'yyyy-mm-dd') as thedate from dual union all
select to_date('2012-11-30', 'yyyy-mm-dd') as thedate from dual union all
select to_date('2012-12-31', 'yyyy-mm-dd') as thedate from dual union all
select to_date('2013-01-31', 'yyyy-mm-dd') as thedate from dual union all
select to_date('2013-02-28', 'yyyy-mm-dd') as thedate from dual
) as monthends
group by owner, to_char(thedate, 'YYYY-MM')
order by 1
如果要为任意范围创建monthends表,可以了解Oracle的connect by
语法。获得一堆月份的简单方法很简单:
select add_month('01Jan2000', rownum) - 1
from project
where rownum < 12 * 20
这将得到2000-2019的月末日期。
答案 1 :(得分:1)
这将返回在打开月份时未关闭的项目数。这听起来像你要求的
SELECT to_char(open_date, 'MON-YYYY') as OpenMonths, count(*) as counts FROM
Project WHERE to_char(open_date,'MON-YYYY') <> to_char(close_date,'MON-YYYY')
GROUP BY to_char(open_date, 'MON-YYYY');
sqlfiddle的链接在这里。 http://www.sqlfiddle.com/#!4/28bf5/1 我将空值更改为其他示例日期,因为DDL的文本未正确检测到它们。
编辑:
使用生成的月/年维度,此查询将起作用
SELECT monthid, count(*) as ProjectsOpen FROM
(
Select * FROm table1 CROSS JOIN mdim WHERE
(to_date(mdim.monthid,'MON-YYYY') >= table1.open_date ) AND (to_date(mdim.monthid,'MON-YYYY') <= table1.close_date)
) GROUP BY monthid;
月份维度类似于
INSERT ALL
INTO mdim
VALUES ('JAN-2012')
INTO mdim
VALUES ('FEB-2012')
INTO mdim
VALUES ('MAR-2012')
INTO mdim
VALUES ('APR-2012')
INTO mdim
VALUES ('MAY-2012')
INTO mdim
VALUES ('JUN-2012')
INTO mdim
VALUES ('JUL-2012')
INTO mdim
VALUES ('AUG-2012')
INTO mdim
VALUES ('SEP-2012')
INTO mdim
VALUES ('OCT-2012')
INTO mdim
VALUES ('NOV-2012')
INTO mdim
VALUES ('DEC-2012')
INTO mdim
VALUES ('JAN-2013')
INTO mdim
VALUES ('FEB-2013')
INTO mdim
VALUES ('MAR-2013')
INTO mdim
VALUES ('APR-2013')
INTO mdim
VALUES ('MAY-2013')
INTO mdim
VALUES ('JUN-2013')
INTO mdim
VALUES ('JUL-2013')
INTO mdim
VALUES ('AUG-2013')
INTO mdim
VALUES ('SEP-2013')
INTO mdim
VALUES ('OCT-2013')
INTO mdim
VALUES ('NOV-2013')
INTO mdim
VALUES ('DEC-2013')
由于SQLFiddle搞砸了csv导入,我正在做一些任意的to_date转换。但是,如果填充月份维度,则第二个查询将获得所需的数据。