Как заполнить значение как ноль, если нет данных для конкретной недели в оракуле - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть таблица со следующей структурой.

Note_title varchar2(100)
Note_created_on date

Теперь в отчете я хочу показать все заметки, созданные еженедельно, поэтому я реализовал для нее следующее решение.

SELECT to_char(Note_created_on - 7/24,'ww')||'/'||to_char(Note_created_on - 7/24,'yyyy') as Week ,
nvl(COUNT(Note_title),'0') as AMOUNT
FROM Notes
GROUP BY to_char(Note_created_on - 7/24,'ww') ,
to_char(Note_created_on -7/24,'yyyy')
ORDER BY to_char(Note_created_on - 7/24,'ww') DESC

И я получаю правильный вывод от него, но предположим, что на неделе 42,45 нет созданной ноты, тогда ее просто не хватает.Пример вывода:

WEEK    AMOUNT
46/2018 3
44/2018 22
43/2018 45
41/2018 1
40/2018 2
39/2018 27
38/2018 23

Итак, как я могу получить нулевые значения для недели 42,45 вместо того, чтобы пропустить их?

Ответы [ 3 ]

0 голосов
/ 14 ноября 2018

Сначала вам нужно будет сгенерировать все недели между каждым годом, после чего осталось бы объединиться с таблицами Notes по неделям и сгруппировать по сгенерированным неделям.Например:

 with weeks
        as ( select level as lvl /*Assume 52 weeks in a calendar year..*/
               from dual 
             connect by level <=52
            )
     ,weeks_year
       as (select distinct 
                  b.lvl||'/'||trunc(Note_created_on,'YYYY') as week_year_val /*From the start of year in Note_created_on*/
            from Notes a
            join weeks b
               on 1=1      
           )
  SELECT a.week_year_val as Week 
         ,COUNT(Note_title) as AMOUNT
     FROM weeks_year a
LEFT JOIN Notes b
       ON a.week_year_val=to_char(b.Note_created_on - 7/24,'ww')||'/'||to_char(b.Note_created_on - 7/24,'yyyy')
GROUP BY a.week_year_val
ORDER BY a.week_year_val DESC
0 голосов
/ 14 ноября 2018

Если вы хотите выполнить это для текущего года , вы можете использовать следующий оператор SQL , который использует такой RIGHT JOIN, как показано ниже:

SELECT d.week as Week,
       nvl(COUNT(Note_title), '0') as AMOUNT
  FROM Notes
 RIGHT JOIN 
(SELECT lpad(level,2,'0')|| '/' ||to_char(sysdate,'yyyy') as week, 
        '0' as amount FROM dual CONNECT BY level <= 53) d
    ON 
      ( d.week = 
 to_char(Note_created_on - 7 / 24, 'ww') ||'/'||to_char(Note_created_on - 7 / 24, 'yyyy') )
 GROUP BY d.week
 ORDER BY d.week DESC;

P.S. Существует распространенное мнение, что год состоит из 52 недель , правда, но усеченный :). Итак, я использовал 53,

Обратите внимание, что select to_char( date'2016-12-31' - 7 / 24, 'ww') from dual дает 53 в качестве образца.

Rextester Demo

0 голосов
/ 14 ноября 2018

Как упомянул jarlh:

Создать список недель:

SELECT TO_CHAR(LEVEL, 'FM00')||'/2018' wk
FROM dual
CONNECT BY LEVEL <= 53

Этот запрос генерирует 53 строки, а уровень - это просто число .. 1 .. 2 .. upto53. Мы форматируем его так, чтобы он стал 01/2018, 02/2018. 53/2018

Если вы планируете использовать этот запрос в другие годы, лучше сделать динамический год:

SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
FROM dual
CONNECT BY LEVEL <= 53

(Кредит Барбаросу за указание на то, что Oracle сообщает, что последний день любого года относится к 53-й неделе, или как-то иначе 7 * 52 = 364)

Мы присоединились кзаписывает данные на него.Я не совсем понял, почему вы вычли 7 часов из даты (часовой пояс?), Но я оставил это.Я убрал сложность подсчета, так как вы, кажется, хотите, чтобы подсчет только записей за определенную неделю.Я также удалил двойной to_char, потому что вы можете сделать все это за одну операцию.Не нужно TO_CHAR(date, 'WW')||'/'||TO_CHAR(date,'YYYY') и т. Д. Вы просто добавляете WW/YYYY в качестве формата.Наш запрос теперь выглядит следующим образом:

SELECT lst.wk as week, COALESCE(amt, 0) as amount FROM
(
  SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
  FROM dual
  CONNECT BY LEVEL <= 52
) lst
LEFT OUTER JOIN
(
  SELECT 
    to_char(Note_created_on - 7/24,'ww/yyyy') as wk,
    COUNT(*) as amt
  FROM Notes
  GROUP BY to_char(Note_created_on - 7/24,'ww/yyyy') 
) dat
ON lst.wk = dat.wk
ORDER BY lst.wk

В течение нескольких недель, когда нет примечаний, левое объединение записывает нулевое значение по отношению к этой неделе, поэтому мы объединяем его, чтобы сделать его равным 0.

Вы можете, конечно, выполнить запрос другими способами (многими способами), вот сравнение:

SELECT lst.wk as week,  COUNT(dat.wk) as amount FROM
(
  SELECT TO_CHAR(LEVEL, 'FM00')||TO_CHAR(sysdate-7/24,'/YYYY') wk
  FROM dual
  CONNECT BY LEVEL <= 52
) lst
LEFT OUTER JOIN
(
  SELECT 
    to_char(Note_created_on - 7/24,'ww/yyyy') as wk
  FROM Notes
) dat
ON lst.wk = dat.wk
GROUP BY lst.wk
ORDER BY lst.wk

В этой форме мы делаем groupby / count после объединения.Подсчитав dat.wk, который для некоторого lst.wk может быть равен NULL, мы можем опустить объединение, потому что count (null) равно 0

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