假设我有一张约会表。
select * from t;
d
-
2014/01/02
2014/02/05
2014/02/12
2014/04/01
什么查询将按月提供总行数?
2014/01 1
2014/02 2
2014/04 1
同样,累计总数
2014/01 1
2014/02 3
2014/04 4
最后,没有行的月份为零值
2014/01 1
2014/02 2
2014/03 0
2014/04 1
特定于Oracle的解决方案是可以接受的。
答案 0 :(得分:3)
假设表名为t 以下记录:
2014/01/02
2014/02/05
2014/02/12
2014/04/01
1)
SELECT *
FROM
(SELECT TO_CHAR(my_date,'yyyy/mm')my_date, COUNT(*)
FROM t
GROUP BY TO_CHAR(my_date,'yyyy/mm')
)
ORDER BY to_date(my_date,'yyyy/mm');
结果:
2014/01 1
2014/02 2
2014/04 1
以下查询: 2)
SELECT my_date, sum(my_count) over ( order by 1 rows unbounded preceding) cumulative
FROM
(SELECT TO_CHAR(my_date,'yyyy/mm')my_date,
COUNT(*) my_count
FROM t
GROUP BY TO_CHAR(my_date,'yyyy/mm')
)
ORDER BY to_date(my_date,'yyyy/mm');
结果累积计数:
2014/01 1
2014/02 3
2014/04 4
3)整年:
SELECT b.all_date,nvl(my_count,0)my_count
FROM
(SELECT TO_CHAR(my_date,'yyyy/mm')my_date,
COUNT(*) my_count
FROM t
GROUP BY TO_CHAR(my_date,'yyyy/mm')
)A,
(SELECT TO_CHAR(add_months(to_date('2014/01/01','yyyy/mm/dd')-1 ,LEVEL),'yyyy/mm') all_date
FROM dual
CONNECT BY level <= 12
) b
WHERE A.mY_date(+) = b.all_date
ORDER BY to_date(b.all_date,'yyyy/mm');
结果:
2014/01 1
2014/02 2
2014/03 0
2014/04 1
2014/05 0
2014/06 0
2014/07 0
2014/08 0
2014/09 0
2014/10 0
2014/11 0
2014/12 0
答案 1 :(得分:1)
ajmalmhd04给出了很好的答案。
这里我们以TRUNC(anydate,&#39; MONTH&#39;)的形式使用TRUNC()返回相关月份的第一天,它保留的数据类型比使用字符串更快大数据集。
另外使用ANSI连接语法。
-- full monthly range over 12 months
-- example, 12 months starting at Jan 1 current year
SELECT ADD_MONTHS(TRUNC(sysdate,'YEAR'),LEVEL) range_month
FROM dual
CONNECT BY level <= 12
- 收集基础数据
SELECT TO_CHAR(the_month,'yyyy-mm-dd') AS the_month, the_count
FROM (
SELECT TRUNC(my_date,'MONTH') AS the_month, COUNT(*) AS the_count
FROM t
GROUP BY TRUNC(my_date,'MONTH')
)
ORDER BY the_month
;
- 产生累积
SELECT
TO_CHAR(the_month,'yyyy-mm-dd') AS the_month
, the_count
, sum(the_count) over(order by the_month rows unbounded preceding) AS cumulative
FROM (
SELECT TRUNC(my_date,'MONTH') AS the_month, COUNT(*) AS the_count
FROM t
GROUP BY TRUNC(my_date,'MONTH')
)
ORDER BY the_month
;
- 将范围与基础数据和由左外连接累积
SELECT
TO_CHAR(Y.range_month,'yyyy-mm-dd') AS the_month
, NVL(T.the_count,0) AS the_count
, sum(T.the_count) over(order by Y.range_month rows unbounded preceding) AS cumulative
FROM
(
SELECT ADD_MONTHS(TO_DATE('2014-01-01','yyyy-mm-dd'),LEVEL) range_month /* fixed date used for example only */
FROM dual
CONNECT BY level <= 12
) Y
LEFT OUTER JOIN (
SELECT TRUNC(my_date,'MONTH') AS the_month, COUNT(*) AS the_count
FROM t
GROUP BY TRUNC(my_date,'MONTH')
) T
ON Y.range_month = T.the_month
ORDER BY
Y.range_month
;
以上内容可在this SQLfiddle demo查看。