Oracle SQL - вернуть запись даты, если результат не найден - PullRequest
0 голосов
/ 05 июня 2019

У меня есть таблицы ниже, и мне нужен мой запрос, чтобы получить количество операций, сгруппированных по дате. Для дат, в которые не будет никаких операций, мне нужно все равно вернуть дату с нулевым счетом. Вроде как:

OPERATION_DATE | COUNT_OPERATION | COUNT_OPERATION2 |
04/06/2019     |            453  |              81  |
05/06/2019     |              0  |               0  |

- ЗАПРОС Я ПРОБОВАЛ

SELECT 
    T1.DATE_OPERATION AS  DATE_OPERATION,
    NVL(T1.COUNT_OPERATION, '0') COUNT_OPERATION,
    NVL(T1.COUNT_OPERATION2, '0') COUNT_OPERATIONX,

FROM
(  
SELECT
    trunc(t.DATE_OPERATION) as DATE_OPERATION,
    count(t.ID_OPERATION) AS COUNT_OPERATION,
    COUNT(CASE WHEN O.OPERATION_TYPE = 'X' THEN 1 END) COUNT_OPERATIONX,
from OPERATION o
    left join OPERATION_TYPE ot on ot.id_operation = o.id_operation
where ot.OPERATION_TYPE in ('X', 'W', 'Z', 'I', 'J', 'V') 
    and TRUNC(t.DATE_OPERATION) >= to_date('01/06/2019', 'DD-MM-YYYY')
    group by trunc(t.DATE_OPERATION)
) T1

- СТОЛЫ

CREATE TABLE OPERATION
(   ID_OPERATION NUMBER NOT NULL,
    DATE_OPERATION DATE NOT NULL,
    VALUE NUMBER NOT NULL )

CREATE TABLE OPERATION_TYPE
(   ID_OPERATION NUMBER NOT NULL,
    OPERATION_TYPE VARCHAR2(1) NOT NULL,
    VALUE NUMBER NOT NULL)  

1 Ответ

1 голос
/ 05 июня 2019

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

Это то, что у вас есть в настоящее время (я использую только таблицу operation; добавьте еще одну самостоятельно):

SQL> with
  2  operation (id_operation, date_operation, value) as
  3    (select 1, date '2019-06-01', 100 from dual union all
  4     select 2, date '2019-06-01', 200 from dual union all
  5     -- 02/06/2019 is missing
  6     select 3, date '2019-06-03', 300 from dual union all
  7     select 4, date '2019-06-04', 400 from dual
  8    )
  9  select o.date_operation,
 10         count(o.id_operation)
 11  from operation o
 12  group by o.date_operation
 13  order by o.date_operation;

DATE_OPERA COUNT(O.ID_OPERATION)
---------- ---------------------
01/06/2019                     2
03/06/2019                     1
04/06/2019                     1

SQL>

Так как нет строк, которые принадлежат 06/06/2019, запрос не может ничего вернуть (вы уже это знаете).


Поэтому добавьте календарь.Если у вас уже есть этот стол, хорошо - используйте его.Если нет, создайте его.Это иерархический запрос, который добавляет level к определенной дате.Я использую 01/06/2019 в качестве отправной точки, создавая 5 дней (обратите внимание на предложение connect by).

SQL> with
  2  operation (id_operation, date_operation, value) as
  3    (select 1, date '2019-06-01', 100 from dual union all
  4     select 2, date '2019-06-01', 200 from dual union all
  5     -- 02/06/2019 is missing
  6     select 3, date '2019-06-03', 300 from dual union all
  7     select 4, date '2019-06-04', 400 from dual
  8    ),
  9  dates (datum) as                              --> this is a calendar
 10    (select date '2019-06-01' + level - 1
 11     from dual
 12     connect by level <= 5
 13    )
 14  select d.datum,
 15         count(o.id_operation)
 16  from operation o full outer join dates d on d.datum = o.date_operation
 17  group by d.datum
 18  order by d.datum;

DATUM      COUNT(O.ID_OPERATION)
---------- ---------------------
01/06/2019                     2
02/06/2019                     0      --> missing in source table
03/06/2019                     1
04/06/2019                     1
05/06/2019                     0      --> missing in source table

SQL>

Вероятно, лучшим вариантом будет динамически создать календарь, чтобы он не зависел от жестко заданных значений, а использовал значения от min(date_operation) до max(date_operation)промежуток времени.Вот и мы:

SQL> with
  2  operation (id_operation, date_operation, value) as
  3    (select 1, date '2019-06-01', 100 from dual union all
  4     select 2, date '2019-06-01', 200 from dual union all
  5     -- 02/06/2019 is missing
  6     select 3, date '2019-06-03', 300 from dual union all
  7     select 4, date '2019-06-04', 400 from dual
  8    ),
  9  dates (datum) as                              --> this is a calendar
 10    (select x.min_datum + level - 1
 11     from (select min(o.date_operation) min_datum,
 12                  max(o.date_operation) max_datum
 13           from operation o
 14          ) x
 15     connect by level <= x.max_datum - x.min_datum + 1
 16    )
 17  select d.datum,
 18         count(o.id_operation)
 19  from operation o full outer join dates d on d.datum = o.date_operation
 20  group by d.datum
 21  order by d.datum;

DATUM      COUNT(O.ID_OPERATION)
---------- ---------------------
01/06/2019                     2
02/06/2019                     0      --> missing in source table
03/06/2019                     1
04/06/2019                     1

SQL>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...