получить количество записей за каждый час за последние 24 часа - PullRequest
0 голосов
/ 03 мая 2018

мне нужно количество записей в каждом часе за последние 24 часа, мне нужно, чтобы мой запрос показывал 0, если в какой-либо конкретный час для этого дня нет записей, я просто могу получить данные за часы, которые в табл.

SELECT TRUNC(systemdate,'HH24') + (trunc(to_char(systemdate,'mi')/10)*10)/24/60 AS date1, 
 count(*) AS txncount
FROM transactionlog 
GROUP BY TRUNC(systemdate,'HH24') + (trunc(to_char(systemdate,'mi')/10)*10)/24/60 order by date1 desc; 

результат:

result set

Что мне делать, чтобы получать данные за каждый час за последние 24 часа?

Ожидаемые данные:

expected data

количество записей в каждом часе за последние 24 часа, начиная с текущей даты .. если в этот конкретный час нет записей, отображается 0.

Ответы [ 3 ]

0 голосов
/ 03 мая 2018

Вам нужно написать последние 24 часа календарную таблицу , затем LEFT JOIN календарную таблицу в исходной таблице.

  1. count(t.systemdate) нужно посчитать t.systemdate, потому что t.systemdate может быть NULL
  2. connect by создать таблицу календаря за последние 24 часа
  3. on предложение TO_CHAR(t.systemdate,'YYYY/MM/DD hh24','nls_language=american') убедитесь, что язык форматирования даты совпадает.

Вы можете попробовать это.

WITH Hours as 
(
  select sysdate + (level/24) dates
  from dual 
  connect by level <= 24
)
SELECT TO_CHAR(h.dates,'YYYY-MM-DD HH24') AS dateHour, count(t.systemdate) AS totlecount
FROM Hours h
LEFT JOIN transactionlog t
on TO_CHAR(t.systemdate,'YYYY/MM/DD hh24','nls_language=american') 
    = TO_CHAR(h.dates,'YYYY/MM/DD hh24','nls_language=american')
GROUP BY h.dates
ORDER BY h.dates

sqlfiddle: http://sqlfiddle.com/#!4/73db7/2


CTE Рекурсивный Версия

Вы также можете использовать CTE Recursive , чтобы написать таблицу календаря

WITH Hours(dates,i) as 
(
   SELECT sysdate,1 
   FROM DUAL
   UNION ALL 
   SELECT sysdate + (i/24),i+1
   FROM Hours
   WHERE i<24
)
SELECT TO_CHAR(h.dates,'YYYY-MM-DD HH24') AS dateHour, count(t.systemdate) AS totlecount
FROM Hours h
LEFT JOIN transactionlog t
on TO_CHAR(t.systemdate,'YYYY/MM/DD hh24','nls_language=american') 
    = TO_CHAR(h.dates,'YYYY/MM/DD hh24','nls_language=american')
GROUP BY h.dates
ORDER BY h.dates

sqlfiddle: http://sqlfiddle.com/#!4/73db7/7

0 голосов
/ 03 мая 2018

Следующее может быть то, что вам нужно. Кажется, он работает, когда я запускаю его в представлении all_objects.

WITH date_range
  AS (SELECT TRUNC(sysdate - (rownum/24),'HH24') as the_hour
        FROM dual
      CONNECT BY ROWNUM <= 1000),
     the_data
  AS (SELECT TRUNC(created, 'HH24')  as cr_ddl, count(*) as num_obj
        FROM all_objects
      GROUP BY TRUNC(created, 'HH24'))   
SELECT TO_CHAR(dr.the_hour,'DD/MM/YYYY HH:MI AM'), NVL(num_obj,0)
FROM date_range dr LEFT OUTER JOIN the_data  ao
     ON ao.cr_ddl =  dr.the_hour
ORDER BY dr.the_hour DESC     

Date_range генерирует запись для каждого часа за последние 24 часа.
'The_data' подсчитывает количество записей в вашей целевой таблице на основе даты, усеченной до часа.
Основной запрос, затем внешний, объединяет два из них, показывая дату и количество из подзапроса.
Я предпочитаю обе части запроса в их собственном CTE, потому что это делает настоящий запрос очень очевидным и «чистым».

В терминах вашего запроса вы хотите это;

WITH date_range
  AS (SELECT TRUNC(sysdate - (rownum/24),'HH24') as the_hour
        FROM dual
      CONNECT BY ROWNUM <= 24),
     the_data
  AS (SELECT TRUNC(systemdate, 'HH24')  as log_date, count(*) as num_obj
        FROM transactionlog 
      GROUP BY TRUNC(systemdate, 'HH24'))   
SELECT TO_CHAR(dr.the_hour,'DD/MM/YYYY HH:MI AM'), NVL(trans_log.num_obj,0)
FROM date_range dr LEFT OUTER JOIN the_data  trans_log
     ON trans_log.log_date =  dr.the_hour
ORDER BY dr.the_hour DESC   
0 голосов
/ 03 мая 2018

Вы можете использовать это:

WITH transactionlog AS 
(
    SELECT TO_DATE('03/05/2018 01:12','dd/mm/yyyy hh24:mi') AS systemdate, 60 AS value 
    FROM dual UNION ALL 
    SELECT TO_DATE('03/05/2018 01:32','dd/mm/yyyy hh24:mi'), 35 FROM dual UNION ALL 
    SELECT TO_DATE('03/05/2018 09:44','dd/mm/yyyy hh24:mi'), 31 FROM dual UNION ALL 
    SELECT TO_DATE('03/05/2018 08:56','dd/mm/yyyy hh24:mi'), 24 FROM dual UNION ALL 
    SELECT TO_DATE('03/05/2018 08:02','dd/mm/yyyy hh24:mi'), 98 FROM dual 
)
, time_range AS 
(
    SELECT TRUNC(sysdate, 'hh24') - 23/24 + (ROWNUM - 1) / 24 AS time1
    FROM all_objects
    WHERE ROWNUM <= 24
)
SELECT TO_CHAR(r.time1, 'mm/dd/yyyy hh:mi AM') AS date1,
    COUNT(t.systemdate) AS txncount
FROM time_range r
LEFT JOIN transactionlog t
ON r.time1 = TRUNC(t.systemdate, 'hh24') --+ 1/24
GROUP BY r.time1
ORDER BY r.time1;

Если 01:12 AM означает 02:00 AM в результате, пропустите код комментария.

Ссылка: Генерация дат между двумя диапазонами дат_AskTOM

Отредактировано: для OP вам нужно только это:

WITH time_range AS 
(
    SELECT TRUNC(sysdate, 'hh24') - 23/24 + (ROWNUM - 1) / 24 AS time1
    FROM all_objects
    WHERE ROWNUM <= 24
)
SELECT TO_CHAR(r.time1, 'mm/dd/yyyy hh:mi AM') AS date1,
    COUNT(t.systemdate) AS txncount
FROM time_range r
LEFT JOIN transactionlog t
ON r.time1 = TRUNC(t.systemdate, 'hh24') --+ 1/24
GROUP BY r.time1
ORDER BY r.time1;
...