За последние 24 часа нас посетили 20854 программиста и 1136 роботов. Сейчас ищут 313 программистов ...

Как исключить айдишники из предыдущего диапазона?

Тема в разделе "MySQL", создана пользователем Сереганек, 3 май 2021.

Метки:
  1. Сереганек

    Сереганек Активный пользователь

    С нами с:
    18 янв 2017
    Сообщения:
    333
    Симпатии:
    27
    У меня есть таблица юзеров и таблица платежей. Нужно взять юзеров за первую неделю года. Затем, для этих юзеров посчитать сколько из них сделали по крайней мере один платеж за первую неделю года. По же самое необходимо посчитать юзеров с первой недели, но только тех, которые делали платежи во второй неделе. Затем, юзеры все той же первой недели, но те, которые делали плажи в третьей недели. При этом в каждой следующей неделе следует исключать из расчета тех юзеров, которые хоть раз уже были учтены в одной из предыдущих недель.
    Аналогичная логока проделывается для юзеров каждой следующей недели. Рабочий алгоритм у меня уже есть для аналогичных задач, который отличается только тем, что не нужно следить, был ли юзер уже посчитан в предыдущих неделях или не был. Я упростил запрос до минимума, чтобы показать в чем у меня проблема.
    Во вложенном селекте я выбираю айдишники юзеров, которые уже попали в предыдущие периоды, чтобы исключить их. Но почему-то это исключение не отрабатывает, один и тот же айдишник попадает в расчет в оба периода. Что здесь не так?

    Код (Text):
    1. SELECT
    2.     u.id,
    3.     (CASE WHEN
    4.              `u`.`created_at` BETWEEN '2021-01-04 00:00:00' AND '2021-01-10 23:59:59'
    5.             AND `purchases`.`created_at` BETWEEN '2021-01-11 00:00:00' AND '2021-01-17 23:59:59'
    6.             and `u`.`id` not in (SELECT `users`.`id`
    7.                                  FROM `users`
    8.                                  WHERE `users`.`created_at` BETWEEN '2021-01-04 00:00:00' AND '2021-01-10 23:59:59'
    9.                                  AND `purchases`.`created_at` BETWEEN '2021-01-04 00:00:00' AND '2021-01-10 23:59:59') THEN 1 END) AS `2021-W02`
    10. from `users` as u;  
    11. INNER JOIN `purchases` ON `purchases`.`user_id` = `users`.`id`  
     
  2. Drunkenmunky

    Drunkenmunky Активный пользователь

    С нами с:
    12 авг 2020
    Сообщения:
    1.476
    Симпатии:
    281
    Вряд ли без самих таблиц кто-то что-то поймет.
    Например.
    Имеются ли в виду даты регистраций пользователей под "взять юзеров за первую неделю" и тд
     
  3. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.068
    Симпатии:
    1.231
    Адрес:
    там-сям
    SELECT u.id FROM users AS u JOIN purchases ...

    > Нужно взять юзеров за первую неделю года.

    WHERE u.created_at BETWEEN :d1 AND :d2

    > необходимо посчитать юзеров с первой недели, но только тех, которые делали платежи во второй неделе

    ... AND purchases.created_at BETWEEN :d3 AND :d4

    > в каждой следующей неделе следует исключать из расчета тех юзеров, которые хоть раз уже были учтены в одной из предыдущих недель

    ... AND u.id NOT IN(...)

    выведет айдишники пользователей, попадающих в условия. без подзапросов, только подготавливай параметры на стороне PHP
    --- Добавлено ---
    допустим ты копишь айдишники пользователей в массиве $userIds

    последнее условие может выглядеть так:
    if ($userIds) {
    $sql .= ' AND u.id NOT IN('.implode(',', $userIds).')';
    }

    после выборки надо добавить айдишники новой недели к тому же массиву $userIds чтобы исключить их в следующем запросе.
    сколько недель проверяешь, столько будет sql-запросов.