GROUP BY не удаляет дубликаты
у меня есть система наблюдения, которую я закодировал, в обзоре списка наблюдения пользователей они увидят список записей, однако список показывает дубликаты, когда в базе данных он показывает только точное, правильное число.
Я пробовал GROUP BY watch.watch_id
, GROUP BY rec.record_id
, ни один из типов групп, которые я пробовал, не удаляет дубликаты. Не знаю, что я делаю не так.
SELECT watch.watch_date,
rec.street_number,
rec.street_name,
rec.city,
rec.state,
rec.country,
usr.username
FROM
(
watchlist watch
LEFT OUTER JOIN records rec ON rec.record_id = watch.record_id
LEFT OUTER JOIN members usr ON rec.user_id = usr.user_id
)
WHERE watch.user_id = 1
GROUP BY watch.watch_id
LIMIT 0, 25
таблица наблюдения выглядит следующим образом:
+----------+---------+-----------+------------+
| watch_id | user_id | record_id | watch_date |
+----------+---------+-----------+------------+
| 13 | 1 | 22 | 1314038274 |
| 14 | 1 | 25 | 1314038995 |
+----------+---------+-----------+------------+
5 ответов
GROUP BY не "удаляет дубликаты". GROUP BY позволяет агрегировать. Если все, что вам нужно, это объединить дублированные строки, используйте SELECT DISTINCT.
если вам нужно объединить строки, которые дублируются в некоторых столбцах, используйте GROUP BY, но вам нужно указать, что делать с другими столбцами. Вы можете либо опустить их (не перечисляя их в предложении SELECT), либо агрегировать их (используя такие функции, как SUM, MIN и AVG). Для пример:
SELECT watch.watch_id, COUNT(rec.street_number), MAX(watch.watch_date)
... GROUP by watch.watch_id
редактировать
ОП попросил некоторых разъяснений.
рассмотреть "вид" -- все данные собраны и включается и где, вызвать, что В. Есть две вещи, которые вы могли бы хотеть сделать.
во-первых, вы могли бы полностью повторяющиеся строки что вы хотите совместить:
a b c
- - -
1 2 3
1 2 3
3 4 5
тогда просто используйте DISTINCT
SELECT DISTINCT * FROM V;
a b c
- - -
1 2 3
3 4 5
или, возможно, частично повторяющиеся строки что вы хотите совместить:
a b c
- - -
1 2 3
1 2 6
3 4 5
эти первые две строки "одинаковы" в некотором смысле, но явно отличаются в другом смысле (в частности, они не быть объединены с помощью SELECT DISTINCT). Вы должны решить, как их объединить. Вы можете отбросить столбец c как несущественный:
SELECT DISTINCT a,b FROM V;
a b
- -
1 2
3 4
или вы можете выполнить какую-то агрегацию на них. Вы могли бы сложить их:
SELECT a,b, SUM(c) "tot" FROM V GROUP BY a,b;
a b tot
- - ---
1 2 9
3 4 5
вы можете добавить выберите наименьшее значение:
SELECT a,b, MIN(c) "first" FROM V GROUP BY a,b;
a b first
- - -----
1 2 3
3 4 5
или вы можете взять среднее (AVG), стандартное отклонение (STD) и любую из множества других функций, которые принимают кучу значений для c и объединяют их в одну.
чем не вариант просто ничего не делать. Если вы просто перечислите не сгруппированные столбцы, СУБД либо выдаст ошибку (Oracle делает это-правильный выбор, imo), либо выберет одно значение более или менее случайным образом (MySQL). Но, как сказал доктор Пирт ," когда вы решите не чтобы решить, вы все равно сделали выбор."
пока SELECT DISTINCT
действительно может работать в вашем случае, важно отметить, почему то, что у тебя не работает.
вы выбираете поля, которые находятся за пределами GROUP BY
. Хотя MySQL позволяет это, точные строки, которые он возвращает для не -GROUP BY
поля не определены.
если вы хотите сделать это с GROUP BY
попробуйте что-то вроде следующего:
SELECT watch.watch_date,
rec.street_number,
rec.street_name,
rec.city,
rec.state,
rec.country,
usr.username
FROM
(
watchlist watch
LEFT OUTER JOIN est8_records rec ON rec.record_id = watch.record_id
LEFT OUTER JOIN est8_members usr ON rec.user_id = usr.user_id
)
WHERE watch.watch_id IN (
SELECT watch_id FROM watch WHERE user_id = 1
GROUP BY watch.watch_id)
LIMIT 0, 25
Я бы никогда не рекомендовал использовать SELECT DISTINCT
, Это очень медленно для больших наборов данных.
попробуйте использовать такие вещи, как EXISTS
.
вы группируетесь по watch.watch_id
и у вас есть два результата, которые имеют различные идентификаторы, поэтому, естественно, они не будут сгруппированы.
кроме того, из отображаемых результатов они имеют разные записи. Это выглядит как совершенно обоснованные ожидаемые результаты. Если вы пытаетесь выбрать только отдельные значения, вам не нужна группа ot, но вы хотите выбрать по отдельным значениям.
SELECT DISTINCT()
...
Если вы говорите, что ваша таблица наблюдения уникальна, то одна (или обе) из других таблиц либо (a) имеет дубликаты, либо (b) не является уникальным ключом, который вы используете.
чтобы подавить дубликаты в результатах, используйте DISTINCT, как говорит @Laykes, или попробуйте
GROUP BY watch.watch_date,
rec.street_number,
rec.street_name,
rec.city,
rec.state,
rec.country,
usr.username
похоже, что вы ожидаете, что все 3 таблицы будут уникальными по своим ключам. Если это так, вы просто маскируете какую-то другую проблему с вашим SQL, пытаясь получить distinct ценности.