SQL-запрос, который находит даты между диапазоном и принимает значения из другого запроса и перебирает диапазон по ним? - PullRequest
0 голосов
/ 08 сентября 2018

Извините, если формулировка этого вопроса странная. Не был уверен, как это сказать, но вот контекст:

Я работаю над приложением, которое показывает некоторые данные о том, как часто отдельные приложения используются, когда пользователи делают запрос с моего веб-сервера. То, как мы берем данные, - каждый раз, когда загружается стартовая страница, она увеличивает таблицу данных с именем WEB_TRACKING на дату ее загрузки. Таким образом, в данных много дыр, например, приложение могло интенсивно использоваться 1 сентября, но не вообще 2 сентября. Что я хочу сделать, так это добавить эти дыры со значением при попаданиях 0. Это то, что я придумал.

Select HIT_DATA.DATE_ACCESSED, HIT_DATA.APP_ID, HIT_DATA.NAME, WORKDAYS.BENCH_DAYS, NVL(HIT_DATA.HITS, 0) from (
    select DISTINCT( TO_CHAR(WEB.ACCESS_TIME, 'MM/DD/YYYY')) as BENCH_DAYS 
    FROM WEB_TRACKING WEB        
) workDays
LEFT join (
    SELECT TO_CHAR(WEB.ACCESS_TIME, 'MM/DD/YYYY') as DATE_ACCESSED, APP.APP_ID, APP.NAME,
    COUNT(WEB.IP_ADDRESS) AS HITS
    FROM WEB_TRACKING WEB
    INNER JOIN WEB_APP APP ON WEB.APP_ID = APP.APP_ID
    WHERE APP.IS_ENABLED = 1  AND (APP.APP_ID = 1 OR APP.APP_ID = 2)
        AND (WEB.ACCESS_TIME > TO_DATE('08/04/2018', 'MM/DD/YYYY') 
        AND WEB.ACCESS_TIME < TO_DATE('09/04/2018', 'MM/DD/YYYY')) 
    GROUP BY TO_CHAR(WEB.ACCESS_TIME, 'MM/DD/YYYY'), APP.APP_ID, APP.NAME
    ORDER BY TO_CHAR(WEB.ACCESS_TIME, 'MM/DD/YYYY'), app_id DESC
) HIT_DATA ON HIT_DATA.DATE_ACCESSED = WORKDAYS.BENCH_DAYS
ORDER BY WORKDAYS.BENCH_DAYS

Возвращает все даты, которые находятся между диапазоном дат, и даже преобразует нулевые совпадения в 0. Однако возвращает нулевое значение для идентификатора приложения и имени приложения. Что имеет смысл, и я понимаю, как дать значение по умолчанию для 1 приложения. Я надеялся, что кто-нибудь поможет мне понять, как это сделать для нескольких приложений.

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

   | APP_ID | NAME       | BENCH_DAYS | HITS |
   | ------ | ---------- | ---------- | ---- |
   |  NULL  | NULL       | 08/04/2018 | 0    |
   |  1     | test_app   | 08/05/2018 | 1    |
   |  NULL  | NULL       | 08/06/2018 | 0    |

Но я хочу это (с несколькими приложениями):

   | APP_ID | NAME       | BENCH_DAYS | HITS |
   | ------ | ---------- | ---------- | ---- |
   |  1     | test_app   | 08/04/2018 | 0    |<- these 0's are converted from null
   |  1     | test_app   | 08/05/2018 | 1    |
   |  1     | test_app   | 08/06/2018 | 0    | <- these 0's are converted from null
   |  2     | prod_app   | 08/04/2018 | 2    |
   |  2     | prod_app   | 08/05/2018 | 0    | <- these 0's are converted from null

Итак, еще раз, чтобы повторить вопрос в этом длинном посте. Как мне заполнить этот запрос, чтобы он заполнил дыры в датах, а также повторно использовал имена и идентификаторы приложений и также заполнил эту информацию?

1 Ответ

0 голосов
/ 08 сентября 2018

Вам нужен список дат, который, вероятно, исходит от генератора чисел, а не из таблицы (если в этой таблице есть дыры, ваш отчет тоже будет)

Пример, каждая дата за последние 30 дней:

select trunc(sysdate-30) + level as bench_days from dual connect by level < 30

Используйте TRUNC вместо того, чтобы превращать дату в строку, чтобы сократить время

Теперь у вас есть список дат, которые вы хотите добавить в повторяющемся идентификаторе и имени приложения:

select * from

    (select trunc(sysdate-30) + level as bench_days from dual connect by level < 30) dat
    CROSS JOIN
    (select app_id, name from WEB_APP WHERE APP.IS_ENABLED = 1 AND APP_ID in (1, 2) app

Теперь у вас есть все ваши даты, перечеркнутые всеми вашими приложениями. 2 приложения и 30 дней сделают набор из 60 строк через перекрестное соединение. Слева присоедините ваши статистические данные к нему, и сгруппируйте / посчитайте / сумму / агрегируйте ...

select app.app_id, app.name, dat.artificialday, COALESCE(stat.ct, 0) as hits from

    (select trunc(sysdate-30) + level as artificialday from dual connect by level < 30) dat
    CROSS JOIN
    (select app_id, name from WEB_APP WHERE APP.IS_ENABLED = 1 AND APP_ID in (1, 2) app
    LEFT JOIN
    (SELECT app_id, trunc(access_time) accdate, count(ip_address) ct from web_tracking group by app_id, trunc(access_time)) stat
    ON
      stat.app_id = app.app_id AND
      stat.accdate = dat.artificialday

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

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