#mysql #sql
Вопрос:
Я хочу получить количество комментариев с интервалом не менее одного часа. Я написал этот запрос, и он отлично работает.
SELECT COUNT(`c`.`id`) `count`
FROM `comments` `c`
WHERE `user_id` = '28' AND (TIMESTAMPDIFF(SECOND, (
SELECT MAX(`created_at`)
FROM `comments`
WHERE `user_id` = '28' AND `created_at` < `c`.`created_at`
), `c`.`created_at`) > 3600 OR TIMESTAMPDIFF(SECOND, (
SELECT MAX(`created_at`)
FROM `comments`
WHERE `user_id` = '28' AND `created_at` < `c`.`created_at`
), `c`.`created_at`) IS NULL)
Но, как вы можете видеть, это утверждение повторяется два раза:
SELECT MAX(`created_at`)
FROM `comments`
WHERE `user_id` = '28' AND `created_at` < `c`.`created_at`
Как я могу написать его чище?
Ответ №1:
Вы снова используете подзапрос, просто чтобы сравнить его с NULL
.
Вы можете избежать этого , применив COALESCE()
его при первом использовании, который вернет число, превышающее 3600, в случае его возврата NULL
, чтобы он мог пройти сравнение:
SELECT COUNT(c.id) count
FROM comments c
WHERE c.user_id = '28'
AND COALESCE(
TIMESTAMPDIFF(
SECOND,
(
SELECT MAX(cc.created_at)
FROM comments cc
WHERE cc.user_id = c.user_id AND cc.created_at < c.created_at
),
c.created_at
),
3601
) > 3600
Если ваша версия MySQL 8.0 , вы можете использовать функцию окна LAG() вместо подзапроса:
WITH cte AS (
SELECT *,
TIMESTAMPDIFF(
SECOND,
LAG(created_at) OVER (PARTITION BY user_id ORDER BY created_at),
created_at
) diff
FROM comments
)
SELECT COUNT(id) count
FROM cte
WHERE user_id = '28' AND (diff IS NULL OR diff > 3600)
Смотрите демонстрацию.