Не совсем так. Возможно, станет понятнее, если мы немного переформатируем запрос от @simon:
SELECT
cu.*,
ue.email
FROM category_users cu
JOIN user_emails ue ON ue.user_id = cu.user_id
WHERE (category_id = '10' AND ue.primary = true)
Условия category_id и ue.primary оба являются частью предложения WHERE, соединенного оператором AND. Если вы удалите одно из условий, вы уберете AND, но оставите предложение WHERE.
Большинство простых SQL-запросов следуют этой форме:
SELECT <нужные_вещи>
FROM <таблицы>
WHERE <условия_фильтрации>
Вы можете полностью опустить предложение WHERE, но тогда вы получите каждую строку из указанных таблиц.
Вот ваш исходный запрос (переформатированный):
SELECT *
FROM category_users
WHERE category_id = '10'
-
“SELECT *” означает, что вы хотите, чтобы запрос возвращал все столбцы из всех задействованных таблиц.
-
“FROM category_users” указывает таблицу, которую вы хотите запросить. Таблица category_users содержит строки, выглядящие примерно так:
| id |
category_id |
user_id |
notification_level |
| 1 |
1 |
1 |
3 |
| 2 |
1 |
2 |
3 |
| 3 |
3 |
1 |
3 |
category_id и user_id называются внешними ключами, потому что они ссылаются на строку в другой таблице (в данном случае на таблицы categories и users). Таким образом, три строки выше означают, что пользователь с id 1 следит за категориями 1 и 3, а пользователь с id 2 следит за категорией 1. Поле notification_level указывает, находятся ли они в статусе Слежение, Слежение за первым сообщением или Отслеживание.
-
“WHERE category_id = '10'” означает, что вас интересуют только строки, где значение в столбце category_id равно 10. Без этой строки вы получили бы каждую строку из таблицы category_users.
@simon предоставил вам новую версию, добавившую адрес электронной почты пользователя:
Этот запрос внес несколько изменений по сравнению с вашим исходным по двум причинам: адреса электронной почты хранятся в отдельной таблице (таблица user_emails), и у пользователей может быть более одного адреса электронной почты.
-
В предложении SELECT:
- “
cu.*” означает “все столбцы из таблицы cu”
- “
ue.email” означает “столбец email из таблицы ue”
-
В предложении FROM:
-
Таблица category_users теперь имеет псевдоним “cu”, что экономит набор текста, если нужно ссылаться на неё более одного раза.
-
Мы выполнили JOIN с таблицей user_emails и присвоили ей псевдоним ue.
Таблица user_emails содержит строки, подобные этим:
Это означает, что пользователь с id 1 имеет два адреса электронной почты: alex@example.com (основной адрес) и alex@other.example.com (вторичный адрес). У пользователя с id 2 только один адрес.
Когда вы выполняете JOIN двух таблиц в SQL, вам обычно нужно указать базе данных условие соединения. Если вы этого не сделаете, база данных не будет знать, какие значения в каждой из таблиц должны совпадать, и вы получите все возможные комбинации строк из двух таблиц. Если бы вы написали этот запрос:
SELECT *
FROM category_users
JOIN user_emails
…с приведенными выше примерами данных, вы получили бы 9 строк: вы бы получили первую строку из category_users три раза, по одному разу с каждой строкой из user_emails, затем аналогично получили бы вторую строку category_users три раза, и наконец, получили бы третью строку category_users три раза.
Условие соединения обычно сообщает базе данных, какой столбец в двух таблицах представляет одно и то же значение. В данном случае столбец category_users.user_id и столбец user_emails.user_id оба представляют одно и то же значение. Записав ON ue.user_id = cu.user_id после JOIN user_emails ue, мы говорим базе данных сопоставить строки user_emails с соответствующими строками category_users.
-
Даже с условием JOIN мы всё равно получим 4 строки для пользователя с ID 1, потому что он следит за 2 категориями и имеет 2 адреса электронной почты — мы получим строку для каждой комбинации. Поэтому @simon добавил дополнительное условие в предложение WHERE, чтобы запрос возвращал только строки с основным адресом электронной почты пользователя. Это условие добавляется к уже существующему условию (ограничению ID категории) — для возврата строки должны иметь category_id = '10' И ue.primary = true.
Затем, поскольку вы не хотели ограничивать поиск одной категорией, вам просто нужно было убрать фильтр category_id. Вы не хотите удалять всё предложение WHERE, потому что всё ещё хотите возвращать только основные адреса электронной почты. Иными словами, ваше условие фильтрации изменилось с:
category_id = '10' AND ue.primary = true
на
ue.primary = true
Уф! Надеюсь, всё стало понятно 