Я читаю это не так, как Кован, и согласен с Ноем ...
Найти все фрукты, где:
- Пользователь 10 не оценил это
- По крайней мере, еще один пользователь сделал оценку
Однако, по моему опыту, использование NOT IN может быть довольно медленным. Итак, я обычно предпочитаю фильтровать с использованием LEFT JOIN так же, как Cowan. Вот несколько вариантов, хотя я не успел протестировать производительность на больших наборах данных ...
SELECT
[f].id,
[f].name
FROM
fruit AS [f]
INNER JOIN
fruit_rating AS [fr]
ON [fr].fruit_id = [f].id
GROUP BY
[f].id,
[f].name
HAVING
SUM(CASE WHEN [fr_exclude].user_id = 10 THEN 1 ELSE 0 END) = 0
SELECT
[f].id,
[f].name
FROM
fruit AS [f]
INNER JOIN
fruit_rating AS [fr]
ON [fr].fruit_id = [f].id
LEFT JOIN
fruit_rating AS [fr_exclude]
ON [fr_exclude].fruit_id = [fr].fruit_id
AND [fr_exclude].user_id = 10
GROUP BY
[f].id,
[f].name
HAVING
MAX([fr_exclude].user_id) IS NULL
Поскольку это работает только для одного пользователя, я бы также подумал о том, чтобы составить таблицу «исключаемых пользователей» и вместо этого использовать левое соединение ...
SELECT
[f].id,
[f].name
FROM
fruit AS [f]
INNER JOIN
fruit_rating AS [fr]
ON [fr].fruit_id = [f].id
LEFT JOIN
excluded_users AS [ex]
AND [ex].user_id = [fr].user_id
GROUP BY
[f].id,
[f].name
HAVING
MAX([ex].user_id) IS NULL
Или что-то гораздо более длинное, но я подозреваю, что это самый быстрый набор больших данных с соответствующими индексами ...
SELECT
[f].id,
[f].name
FROM
fruit [f]
INNER JOIN
(
SELECT
fruit_id
FROM
fruit_rating
GROUP BY
fruit_id
)
AS [rated]
ON [rated].fruit_id = [f].id
LEFT JOIN
(
SELECT
[fr].fruit_id
FROM
fruit_rating AS [fr]
INNER JOIN
excluded_users AS [ex]
ON [ex].user_id = [fr].user_id
GROUP BY
[fr].fruit_id
)
AS [excluded]
ON [rated].fruit_id = [excluded].fruit_id
WHERE
[excluded].fruit_id IS NULL
GROUP BY
[f].id,
[f].name