#sql #postgresql
#sql #postgresql
Вопрос:
У меня есть две таблицы, «просмотр страниц» и «комментарии», в которых хранятся новые посещения веб-страниц и новые комментарии соответственно.
ПРОСМОТР СТРАНИЦ
ID | идентификатор страницы | created_at |
---|---|---|
1 | 1111 | 2021-12-02T04:55:26.779 Z |
2 | 1442 | 2021-12-02T02:25:32.219 Z |
3 | 1111 | 2021-12-02T04:55:26.214 Z |
Комментарии
ID | идентификатор страницы | … | created_at |
---|---|---|---|
1 | 1024 | … | 2021-12-02T04:55:26.779 Z |
2 | 1111 | … | 2021-12-02T02:25:32.219 Z |
3 | 3849 | … | 2021-12-02T04:55:26.214 Z |
Я хочу объединить данные из обеих таблиц за последний 1 час для использования в аналитике, чтобы они выглядели как таблица ниже.
ДАННЫЕ СТРАНИЦЫ
идентификатор страницы | количество посещений | comment_count | created_at |
---|---|---|---|
1024 | 14 | 3 | 2021-12-02T04:55:26.779 Z |
1111 | 11 | 8 | 2021-12-02T02:25:32.219 Z |
3849 | 1 | 0 | 2021-12-02T04:55:26.214 Z |
2412 | 0 | 1 | 2021-12-02T04:55:26.779 Z |
SELECT page_visits.page_id , COUNT(page_visits.id) AS visitCount , COALESCE(cmts.cmt_cnt,0) AS commentCount FROM page_visits LEFT OUTER JOIN ( SELECT page_id , COUNT(*) AS cmt_cnt FROM comments WHERE created_at gt;= NOW() - INTERVAL '1 HOUR' GROUP BY page_id ) AS cmts ON cmts.page_id = page_visits.page_id WHERE page_visits.created_at gt;= NOW() - INTERVAL '1 HOUR' GROUP BY page_visits.page_id, cmts.cmt_cnt;
На данный момент у меня есть приведенный выше код, однако он печатает строку только тогда, когда comment_count равен нулю, но он не делает то же самое, когда visit_count равен 0, а comment_count gt; 0. Мой первый вопрос заключается в том, как заставить его печатать, даже если результат visit_count равен 0. Потому что кто-то мог зайти на страницу час назад, но прокомментировать ее только позже.
Во-вторых, я пытаюсь запускать этот код каждый час с использованием pg_cron, и я знаю, что могу запускать функцию непосредственно в планировщике cron, однако я не могу превратить приведенный выше код в рабочую функцию postgres, которая вставляет новую строку в таблицу «page_data» каждый раз, когда она вызывается.
Может ли кто-нибудь помочь мне с этими 2 проблемами? Спасибо.
Комментарии:
1. Добавьте сведения о вашей таблице страниц также в вопрос
Ответ №1:
Рассмотрим полное объединение двух агрегатов
SELECT page_visits.page_id , COALESCE(vsts.vst_cnt, 0) AS visitCount , COALESCE(cmts.cmt_cnt, 0) AS commentCount FROM ( SELECT page_id , COUNT(*) AS vst_cnt FROM page_visits WHERE created_at gt;= NOW() - INTERVAL '1 HOUR' GROUP BY page_id ) AS vsts FULL OUTER JOIN ( SELECT page_id , COUNT(*) AS cmt_cnt FROM comments WHERE created_at gt;= NOW() - INTERVAL '1 HOUR' GROUP BY page_id ) AS cmts ON cmts.page_id = vsts.page_id
В качестве альтернативы можно объединить запрос ОБЪЕДИНЕНИЯ обеих таблиц:
SELECT page_id , SUM(vst_n) AS vst_cnt , SUM(cmt_n) AS cmt_cnt FROM ( SELECT page_id, 1 AS vst_n, 0 AS cmt_n FROM page_visits WHERE created_at gt;= NOW() - INTERVAL '1 HOUR' UNION ALL SELECT page_id, 0 AS vst_n, 1 AS cmt_n FROM comments WHERE created_at gt;= NOW() - INTERVAL '1 HOUR' ) AS sub GROUP BY page_id
Что касается последнего вопроса, если я вас понимаю, просто запустите запрос «вставить-выбрать» из приведенного выше запроса. Не совсем уверен , как вы агрегировали created_at
, но добавьте MIN
или MAX
к приведенным выше агрегациям и включите дополнительный столбец ниже:
INSERT INTO page_data (page_id, visit_count, comment_count) SELECT ...above query...
Комментарии:
1. Большое вам спасибо за вашу помощь! 1-й ответ не совсем сработал для меня, потому что page_visits.page_id не обязательно содержит конкретный идентификатор страницы, который находится в таблице комментариев. Это связано с тем, что кто-то, возможно, посетил страницу за час до этого, но прокомментировал ее только позже. Поэтому в таких случаях он возвращал значение null для идентификатора страницы. Второй ответ, однако, работает именно так, как задумывалось, так что спасибо вам за это. Могу я спросить, зачем добавлять МИНИМАЛЬНОЕ/МАКСИМАЛЬНОЕ значение в агрегации?
2. У меня была небольшая проблема с именем
FULL OUTER JOIN
в запросе. Можете ли вы проверять и сообщать об ошибках? Этот тип соединения вернет либо совпадающие, либо не совпадающие идентификаторы страниц между посещениями и комментариями (т. Е. Значение NULL в любой таблице). Он должен возвращать тот же результат,UNION
что и запрос.3. И min/max — это заполнить
created_at
поле в вашей итоговойpage_data
таблице. Поскольку эта таблица агрегируется поpage_id
, было неясно, как получить эти данные о дате.MIN(created_at)
Может быть, это сработает? ИлиMAX
? Но обязательно добавьте поле в базовые подзапросы.