2016-08-02 5 views
0

У меня есть таблица, которая содержит отзывы о продукте. У него есть тип обратной связи (положительный, отрицательный), который является текстовым столбцом, дата, на которую были сделаны комментарии. Мне нужно получить общее количество положительных и отрицательных отзывов за определенный период времени. Например, если диапазон дат составляет 30 дней, мне нужно получить общее количество положительных и отрицательных отзывов в течение 4 недель, если диапазон дат составляет 6 месяцев, мне нужно получить общее количество положительных и отрицательных отзывов за каждый месяц. Как группировать счет на основе даты.как группировать столбец даты на основе диапазона дат в oracle

 
+------+------+----------+----------+---------------+--+--+--+ 
| Slno | User | Comments | type | commenteddate | | | | 
+------+------+----------+----------+---------------+--+--+--+ 
| 1 | a | aaaa  | positive | 22-jun-2016 | | | | 
| 2 | b | bbb  | positive | 1-jun-2016 | | | | 
| 3 | c | qqq  | negative | 2-jun-2016 | | | | 
| 4 | d | ccc  | neutral | 3-may-2016 | | | | 
| 5 | e | www  | positive | 2-apr-2016 | | | | 
| 6 | f | s  | negative | 11-nov-2015 | | | | 
+------+------+----------+----------+---------------+--+--+--+ 

Запрос я попытался это

выбрать тип, ТО_СНАК (commenteddate, 'ДД-ММ-ГГГГ'), Count (тип) от комментариев GROUP BY типа, to_char (commenteddate, 'ДД-ММ YYYY ');

+0

Пожалуйста, покажите схему таблицы, выборочные данные и ожидаемый результат, и что вы пробовали. Благодарю. – OldProgrammer

+0

Я добавил пример таблицы и запроса. Мне нужно сгруппировать тип на основе интервалов дат. Например, если интервал дат составляет 30 дней, мне нужно получить общее количество положительных и отрицательных отзывов в течение 4 недель, если диапазон дат составляет 6 месяцев, мне нужно получить общее количество положительных и отрицательных отзывов за каждый месяц. Как группировать счет на основе даты. Я пытаюсь выполнить этот запрос в хранимой процедуре. Интервал ввода - это интервал – hemsush

+0

. Пожалуйста, также покажите ОЖИДАЕМЫЙ ВЫХОД из этих данных образца. – OldProgrammer

ответ

0

Вот удар в банке ...

Предположения:

  • вы хотите, чтобы иметь возможность переключать группировки в еженедельно или ежемесячно только
  • начало первого периода будет первая дата в данных обратной связи; Интервалы будут рассчитываться из этой начальной даты
  • выхода будет показывать значение обратной связи, период времени, отсчет
  • периодов времени не перекрывается, так периоды будет х -> х + интервал - 1 день
  • время суток не важно (время комментировал даты всегда 00:00:00)

Во-первых, создать некоторые выборочные данные (100 строк):

drop table product_feedback purge; 

create table product_feedback 
as 
select rownum as slno 
, chr(65 + MOD(rownum, 26)) as userid 
, lpad(chr(65 + MOD(rownum, 26)), 5, chr(65 + MOD(rownum, 26))) as comments 
, trunc(sysdate) + rownum + trunc(dbms_random.value * 10) as commented_date 
, case mod(rownum * TRUNC(dbms_random.value * 10), 3) 
     when 0 then 'positive' 
     when 1 then 'negative' 
     when 2 then 'neutral' end as feedback 
from dual 
connect by level <= 100 
; 

Вот что выглядит мой пример данных, как:

select * 
from product_feedback 
; 

SLNO USERID COMMENTS COMMENTED_DATE FEEDBACK 
1 B BBBBB 2016-08-06 neutral 
2 C CCCCC 2016-08-06 negative 
3 D DDDDD 2016-08-14 positive 
4 E EEEEE 2016-08-16 negative 
5 F FFFFF 2016-08-09 negative 
6 G GGGGG 2016-08-14 positive 
7 H HHHHH 2016-08-17 positive 
8 I IIIII 2016-08-18 positive 
9 J JJJJJ 2016-08-12 positive 
10 K KKKKK 2016-08-15 neutral 
11 L LLLLL 2016-08-23 neutral 
12 M MMMMM 2016-08-19 positive 
13 N NNNNN 2016-08-16 neutral 
... 

Теперь для забавной части. Вот суть:

  • выяснить, что самые ранние и последние комментируемые даты в данных
  • включают запрос, где вы можете установить период времени (до «НЕДЕЛИ» или «МЕСЯЦЕВ»)
  • генерируют все (еженедельные или ежемесячные) периоды времени между минимальными/максимальными датами
  • присоединяйте обратную связь продукта к периодам времени (прокомментированная дата между началом и концом) с внешним соединением в случае, если вы хотите видеть все периоды времени, независимо от того, не было никакой обратной связи
  • группа объединенный результат по обратной связи, начало периода, д конец периода, а также создать столбец для подсчета одним из 3 возможных значений обратной связи

х

with 
min_max_dates -- get earliest and latest feedback dates 
as 
(select min(commented_date) min_date, max(commented_date) max_date 
from product_feedback 
) 
, time_period_interval 
as 
(select 'MONTHS' as tp_interval -- set the interval/time period here 
    from dual 
) 
, -- generate all time periods between the start date and end date 
time_periods (start_of_period, end_of_period, max_date, time_period) -- recursive with clause - fun stuff! 
as 
(select mmd.min_date as start_of_period 
     , CASE WHEN tpi.tp_interval = 'WEEKS' 
      THEN mmd.min_date + 7 
      WHEN tpi.tp_interval = 'MONTHS' 
      THEN ADD_MONTHS(mmd.min_date, 1) 
      ELSE NULL 
     END - 1 as end_of_period 
, mmd.max_date 
, tpi.tp_interval as time_period 
    from time_period_interval tpi 
     cross join 
     min_max_dates mmd 
UNION ALL 
select CASE WHEN time_period = 'WEEKS' 
      THEN start_of_period + 7 * (ROWNUM) 
      WHEN time_period = 'MONTHS' 
      THEN ADD_MONTHS(start_of_period, ROWNUM) 
      ELSE NULL 
     END as start_of_period 
, CASE WHEN time_period = 'WEEKS' 
      THEN start_of_period + 7 * (ROWNUM + 1) 
      WHEN time_period = 'MONTHS' 
      THEN ADD_MONTHS(start_of_period, ROWNUM + 1) 
      ELSE NULL 
     END - 1 as end_of_period 
, max_date 
, time_period 
from time_periods 
where end_of_period <= max_date 
) 
-- now put it all together 
select pf.feedback 
    , tp.start_of_period 
    , tp.end_of_period 
    , count(*) as feedback_count 
from time_periods tp 
left outer join 
product_feedback pf 
on pf.commented_date between tp.start_of_period and tp.end_of_period 
group by tp.start_of_period 
     , tp.end_of_period 
     , pf.feedback 
order by pf.feedback 
     , tp.start_of_period 
; 

Выход:

negative 2016-08-06 2016-09-05 6 
negative 2016-09-06 2016-10-05 7 
negative 2016-10-06 2016-11-05 8 
negative 2016-11-06 2016-12-05 1 
neutral  2016-08-06 2016-09-05 6 
neutral  2016-09-06 2016-10-05 5 
neutral  2016-10-06 2016-11-05 11 
neutral  2016-11-06 2016-12-05 2 
positive 2016-08-06 2016-09-05 17 
positive 2016-09-06 2016-10-05 16 
positive 2016-10-06 2016-11-05 15 
positive 2016-11-06 2016-12-05 6 

- EDIT -

Новые и улучшенные, все в одной простой в использовании процедуре. (Я предполагаю, что вы можете настроить процедуру для использования запроса так, как вам нужно.) Я сделал некоторые изменения, чтобы упростить операторы CASE в нескольких местах и ​​отметить, что по какой-либо причине использование LEFT OUTER JOIN в главном SELECT приводит к ошибке ORA-600 для меня, поэтому я переключил ее на INNER JOIN.

CREATE OR REPLACE PROCEDURE feedback_counts(p_days_chosen IN NUMBER, p_cursor OUT SYS_REFCURSOR) 
AS 
BEGIN 

OPEN p_cursor FOR 
    with 
    min_max_dates -- get earliest and latest feedback dates 
    as 
    (select min(commented_date) min_date, max(commented_date) max_date 
    from product_feedback 
    ) 
    , time_period_interval 
    as 
    (select CASE 
      WHEN p_days_chosen BETWEEN 1 AND 10 THEN 'DAYS' 
      WHEN p_days_chosen > 10 AND p_days_chosen <=31 THEN 'WEEKS' 
      WHEN p_days_chosen > 31 AND p_days_chosen <= 365 THEN 'MONTHS' 
      ELSE '3-MONTHS' 
     END as tp_interval -- set the interval/time period here 
     from dual --(SELECT p_days_chosen as days_chosen from dual) 
    )  
    , -- generate all time periods between the start date and end date 
    time_periods (start_of_period, end_of_period, max_date, tp_interval) -- recursive with clause - fun stuff! 
    as 
    (select mmd.min_date as start_of_period 
      , CASE tpi.tp_interval 
       WHEN 'DAYS' 
       THEN mmd.min_date + 1 
       WHEN 'WEEKS' 
       THEN mmd.min_date + 7 
       WHEN 'MONTHS' 
       THEN mmd.min_date + 30 
       WHEN '3-MONTHS' 
       THEN mmd.min_date + 90 
       ELSE NULL 
      END - 1 as end_of_period 
    , mmd.max_date 
    , tpi.tp_interval 
     from time_period_interval tpi 
      cross join 
      min_max_dates mmd 
    UNION ALL 
    select CASE tp_interval 
       WHEN 'DAYS' 
       THEN start_of_period + 1 * ROWNUM 
       WHEN 'WEEKS' 
       THEN start_of_period + 7 * ROWNUM 
       WHEN 'MONTHS' 
       THEN start_of_period + 30 * ROWNUM 
       WHEN '3-MONTHS' 
       THEN start_of_period + 90 * ROWNUM 
       ELSE NULL 
      END as start_of_period 
     , start_of_period 
      + CASE tp_interval 
       WHEN 'DAYS' 
       THEN 1 
       WHEN 'WEEKS' 
       THEN 7 
       WHEN 'MONTHS' 
       THEN 30 
       WHEN '3-MONTHS' 
       THEN 90 
       ELSE NULL 
      END * (ROWNUM + 1) 
      - 1 as end_of_period 
    , max_date 
    , tp_interval 
    from time_periods 
    where end_of_period <= max_date 
    ) 
    -- now put it all together 
    select pf.feedback 
     , tp.start_of_period 
     , tp.end_of_period 
     , count(*) as feedback_count 
    from time_periods tp 
    inner join -- currently a bug that prevents the procedure from compiling with a LEFT OUTER JOIN 
    product_feedback pf 
    on pf.commented_date between tp.start_of_period and tp.end_of_period 
    group by tp.start_of_period 
      , tp.end_of_period 
      , pf.feedback 
    order by tp.start_of_period 
      , pf.feedback 
    ; 
END; 

Тест процедура (в чем-то вроде SQLPlus или SQL Developer):

var x refcursor 
exec feedback_counts(10, :x) 
print :x 
+0

Я хочу сгруппировать, если выбранных дней меньше 10, мне нужно получить количество отзывов за каждый день. Если выбранные дни превышают 10 и менее 31 дня, вам необходимо сгруппироваться в течение 7 дней. Если выбранные дни превышают месяц и менее года, вам необходимо сгруппироваться в течение 30 дней, если это больше, чем год требуется для группы в течение 90 дней – hemsush

+0

Дни, выбранные как? Где? Каким механизмом? –

+0

Выбранные дни отправляются в качестве номера в хранимую процедуру. Мне нужно знать, как я могу изменить запрос, – hemsush

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