2014-08-28 6 views
1

Предположим, у меня есть таблица дат.Подведение итогов по дате

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 

оракул-конкретное решение является приемлемым.

ответ

3

Предполагая имя таблицы, как т со следующими записями:

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 
+0

блестящий, большое спасибо! –

1

Некоторые незначительные вариации на хорошо продуман ответ по ajmalmhd04.

Здесь мы используем TRUNC() в виде TRUNC (anydate, 'MONTH), который возвращает 1-й день соответствующего месяца и сохраняет тип данных, который может быть быстрее, чем работа со строками в больших наборах данных.

Дополнительно используется синтаксис ANSI join.

-- 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.

Смежные вопросы