Показать пользователей, которые еще не создали проекты в этом месяце в определенном городе - PullRequest
2 голосов
/ 23 мая 2019

У меня есть этот запрос, который отображает клиентов, которые не создали проект в этом месяце.

SELECT u.userName
FROM (SELECT DISTINCT userName FROM projects) u
LEFT JOIN projects p
    ON u.userName = p.userName AND
       MONTH(p.date) = MONTH(CURRENT_DATE()) AND
       YEAR(p.date) = YEAR(CURRENT_DATE())
WHERE
    p.userName IS NULL

Живой пример: http://sqlfiddle.com/#!9/53de526/5

Теперь я хочу отфильтровать их по городам. Я пробовал разные вещи, но ни одна из них не работает.

Есть идеи?

Спасибо

Ответы [ 5 ]

1 голос
/ 23 мая 2019

Исходя из вашего вопроса и примера, я придумал это ... Попробуйте и посмотрите, хотите ли вы этого.

SELECT u.userName, u.city
FROM (SELECT DISTINCT userName, city FROM projects) u
LEFT JOIN projects p
    ON u.userName = p.userName AND
       MONTH(p.date) = MONTH(CURRENT_DATE()) AND
       YEAR(p.date) = YEAR(CURRENT_DATE())      
WHERE
    p.userName IS NULL
    and u.city = 'Paris'
1 голос
/ 23 мая 2019

Есть много способов достичь этого. Вот один из них:

SELECT
  p.*
FROM
  projects AS p
  INNER JOIN
  (
    SELECT
      userName
      ,MAX(date) AS max_date
    FROM 
      projects p
    GROUP BY
        userName
    HAVING
      max_date < DATE_FORMAT(CURRENT_DATE, '%Y-%m-01')
  ) AS mp
  ON p.userName = mp.userName AND p.date = mp.max_date
WHERE
  p.city = 'Bordeaux'

Это находит максимальное значение date, фильтрует по тем, которые не встречаются в текущем месяце, и объединяет результаты обратно в исходную таблицу, где мы затем фильтруем по city. В качестве примера я показываю 'Bordeaux', но вы можете ввести любое значение (значения).

0 голосов
/ 23 мая 2019

Просто используйте агрегацию:

select p.username
from projects p
group by p.username
having sum( month(p.date) = month(CURRENT_DATE()) and
            year(p.date) = year(CURRENT_DATE()) and
          ) = 0;

Вы упомянули город.Похоже, что ваши данные денормализованы, и city для пользователя , а не проекта .Если это так, просто поместите его в select и group by:

select p.username, p.city
from projects p
group by p.username, p.city
having sum( month(p.date) = month(CURRENT_DATE()) and
            year(p.date) = year(CURRENT_DATE()) and
          ) = 0;

Обычно у вас будет отдельная таблица пользователей.Очевидно, что приведенное выше вернет только тех пользователей, у которых есть проект.Однако с помощью отдельной таблицы вы также можете получить пользователей с проектами no .Для этого я бы использовал not exists:

select u.*
from users u
where not exists (select 1
                  from projects p
                  where month(p.date) = month(CURRENT_DATE()) and
                        year(p.date) = year(CURRENT_DATE())
                 );

И вы получите город вместе с другой информацией.

0 голосов
/ 23 мая 2019

Спецификация немного неясна.

Мы можем генерировать пары (имя пользователя, город), в которых в текущем месяце нет подходящего проекта. Если у нас нет источника для списка значений города, мы можем получить его из таблицы проектов, так же как мы получили список имени пользователя:

SELECT u.username
     , c.city
  FROM ( SELECT pu.username
           FROM projects pu
          GROUP
             BY pu.username
       ) u
 CROSS
  JOIN ( SELECT pc.city
           FROM projects pc
          GROUP
             BY pc.city
       ) c
    -- anti-join    
  LEFT
  JOIN projects p
    ON p.username = u.username
   AND p.city     = c.city
   AND p.date     >= DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL 0 MONTH
   AND p.date     <  DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL 1 MONTH
 WHERE p.username IS NULL
 ORDER
    BY u.username
     , c.city

Если мы хотим «фильтровать», мы можем добавить к предложению WHERE ...

 WHERE p.username IS NULL
   AND c.city = 'Paris'

Или мы могли бы просто включить это условие во встроенное представление c

SELECT u.username
     , c.city
  FROM ( SELECT pu.username
           FROM projects pu
          GROUP
             BY pu.username
       ) u
 CROSS
  JOIN ( SELECT pc.city
           FROM projects pc
          WHERE pc.city = 'Paris'
          GROUP
             BY pc.city
       ) c
    -- anti-join    
  LEFT
  JOIN projects p
    ON p.username = u.username
   AND p.city     = c.city
   AND p.date     >= DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL 0 MONTH
   AND p.date     <  DATE_FORMAT(NOW(),'%Y-%m-01') + INTERVAL 1 MONTH
 WHERE p.username IS NULL
 ORDER
    BY u.username
     , c.city
0 голосов
/ 23 мая 2019
SELECT u.userName, u.city
        FROM (SELECT DISTINCT * FROM projects) u
        LEFT JOIN projects p
            ON u.userName = p.userName AND
               MONTH(p.date) = MONTH(CURRENT_DATE()) AND
               YEAR(p.date) = YEAR(CURRENT_DATE())      
        WHERE
            p.userName IS NULL AND u.city='Paris'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...