Запрос игнорирует одно из предложений where, есть идеи, почему это происходит?

#mysql #sql

Вопрос:

У меня есть два стола, activity и users . Я пытаюсь извлечь данные, используя несколько предложений where.

 SELECT SUM(activity.step_points) AS s_points
, `activity`.`user_id`
, `users`.`id`
, `users`.`app_id`
, `users`.`country_id`
FROM `activity` 
LEFT JOIN `users` ON `users`.`id` = `activity`.`user_id` 
WHERE `users`.`is_active` = 1 AND 
`users`.`is_test_account` = 0 AND 
`users`.`app_id` = 3 AND 
`users`.`country_id` = 1 AND 
`users`.`phone` NOT LIKE "0000%" OR 
`users`.`phone` IS NULL AND 
`users`.`is_subscribed` = 1 AND 
(`users`.`email` NOT LIKE "%@mycompanyname.net" OR 
 `users`.`email` IS NULL) AND 
YEAR(`activity`.`created_at`) = "2021" AND 
MONTH(`activity`.`created_at`) = "06" 
GROUP BY `activity`.`user_id` 
ORDER BY `s_points` DESC LIMIT 100 OFFSET 0
 

Но я думаю users.country_id = 1 , что этим пренебрегают. Вы можете видеть, что мне нужны только строки, относящиеся к идентификатору страны 1. Но я тоже получаю идентификатор страны 2, 3.

скриншот таблицы

Почему это происходит?

Комментарии:

1. Вам нужно быть осторожным, когда у вас есть сочетание предложений » И » с » ИЛИ «где». Попробуйте использовать скобки, чтобы убедиться, что они правильно интерпретированы.

2. @Найджелрен так правдив

3. so true Означает ли это, что ваша проблема теперь решена?

4. @JamesZ да, это решило мою проблему

5. LEFT JOIN x... WHERE x =... это то же самое, что INNER JOIN x...

Ответ №1:

Вам нужно правильно использовать круглые скобки в WHERE предложении, чтобы OR не доминировать над AND s:

 SELECT . . .
FROM activity a JOIN 
     users u
     ON u.id = a.id 
WHERE u.is_active = 1 AND 
      u.is_test_account = 0 AND 
      u.app_id = 3 AND 
      u.country_id = 1 AND 
      (u.phone NOT LIKE '0000%' OR u.phone IS NULL) AND 
      u.is_subscribed = 1 AND 
      (u.email NOT LIKE '%@mycompanyname.net OR u.email IS NULL) AND 
      (a.created_at >= '2021-01-01' AND a.created_at < '2022-01-01'
 

Обратите внимание на другие изменения в коде:

  • Вы выполняете фильтрацию по обеим таблицам, поэтому внешнее соединение не подходит. WHERE Предложение все равно превращает его во внутреннее соединение.
  • Псевдонимы таблиц облегчают написание и чтение кода.
  • Все обратные ссылки просто усложняют написание и чтение кода и не нужны.
  • Стандартный разделитель SQL для строк-одинарные кавычки. Используйте их, если у вас нет веских причин для предпочтения двойных кавычек.
  • Для сравнения дат может быть быстрее избежать функций, отсюда и изменение для сравнения за год. Это помогает оптимизатору.