Лучший способ запустить SQL-запрос для разных дат

У меня есть приложение PHP, которое записывает сеансы различных устройств, подключенных к серверу. В базе есть таблица session со столбцами device_id, start_date, end_date. Чтобы узнать количество устройств, подключенных в определенную дату, я могу использовать запрос:

SELECT COUNT(DISTINCT device_id)
FROM session
WHERE :date >= start_date AND (:date <= end_date OR end_date IS NULL)

где :date передается в качестве параметра подготовленному оператору.

Это прекрасно работает, но если я хочу узнать количество устройств на каждый день в году, это требует выполнения 365 запросов, и я боюсь, что все может стать очень медленным. Кажется неправильным повторять дату в PHP, мне кажется, что должен быть более оптимальный способ сделать это с помощью одного запроса к базе данных.

  1. Можно ли это сделать одним запросом?

  2. Будет ли это на самом деле быстрее, чем повторять дату в PHP при выполнении нескольких запросов?


РЕДАКТИРОВАТЬ, чтобы ответить на комментарии:

  • Мне нужно число для каждого отдельного дня (например, чтобы нарисовать график), а не просто сумма

  • тип данных ДАТА

Вы пытались просто установить дату начала на 2021-01-01 и дату окончания на 2021-12-31 (например)? Это даст вам все сеансы в течение года. Вы наложили на себя ограничение, используя одно значение :date дважды для двух разных параметров в вашем SQL, а это означает, что вы никогда не сможете просмотреть более одной даты.

ADyson 28.03.2022 14:42

Конечно, вам может понадобиться немного изменить запрос, чтобы он проверял, является ли start_date больше, чем первый параметр даты, а также меньше, чем второй. Или вам нужно увидеть, соответствует ли сеанс перекрывается диапазону дат? например если дата начала предшествует первой дате, а дата окончания — после нее, хотите ли вы, чтобы она была включена в результаты?

ADyson 28.03.2022 14:44

Вы хотите результаты за каждый день в этом диапазоне? И каков тип данных дат начала и окончания?

Salman A 28.03.2022 14:45
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
3
41
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если я правильно понимаю, то сначала нужна таблица дат, что-то вроде:

create table dates(dt date);
insert into dates(dt) values
('2001-01-01'),
('2001-01-02'),
...
('2100-12-31')

И используйте такой запрос:

select dates.dt, count(session.device_id)
from dates
join session on start_date <= dates.dt and (dates.dt <= end_date or end_date is null)
-- change to left join to include zero counts
where dates.dt >= :date1 and dates.dt <= :date2
group by dates.dt

PS: поскольку вы упомянули диаграммы, я мог бы добавить, что можно избежать таблицы дат. Однако результат будет содержать только даты изменения количества устройств. API-интерфейсы диаграмм обычно принимают такие данные, но по-прежнему создают точки данных для всех промежуточных дат.

Это сработало, спасибо, я бы не подумал добавить еще одну таблицу. Я должен не забыть обновить его до 2100 года!

user153991 28.03.2022 17:43

Если устройство может отображаться дважды на одном dt, вам может понадобиться DISTINCT внутри COUNT().

Rick James 29.03.2022 07:13

Другие вопросы по теме