В запросе MySQL при использовании опции DISTINCT
применяется ORDER BY
после удаления дубликатов? Если нет, есть ли способ сделать так? Я думаю, что это вызывает некоторые проблемы с моим кодом.
EDIT :
Вот еще информация о том, что вызывает мою проблему. Я понимаю, что на первый взгляд этот порядок не был бы важен, так как я имею дело с повторяющимися строками. Однако это не совсем так, поскольку я использую INNER JOIN
для сортировки строк.
Скажем, у меня есть таблица потоков форума, содержащая эти данные:
+----+--------+-------------+ | id | userid | title | +----+--------+-------------+ | 1 | 1 | Information | | 2 | 1 | FAQ | | 3 | 2 | Support | +----+--------+-------------+
У меня также есть набор сообщений в другой таблице, например:
+----+----------+--------+---------+ | id | threadid | userid | content | +----+----------+--------+---------+ | 1 | 1 | 1 | Lorem | | 2 | 1 | 2 | Ipsum | | 3 | 2 | 2 | Test | | 4 | 3 | 1 | Foo | | 5 | 2 | 3 | Bar | | 6 | 3 | 5 | Bob | | 7 | 1 | 2 | Joe | +----+----------+--------+---------+
Я использую следующий запрос MySQL для получения всех потоков, а затем сортирую их на основе последнего сообщения (предполагая, что сообщения с более высокими идентификаторами более свежие:
SELECT t.* FROM Threads t INNER JOIN Posts p ON t.id = p.threadid ORDER BY p.id DESC
Это работает и генерирует что-то вроде этого:
+----+--------+-------------+ | id | userid | title | +----+--------+-------------+ | 1 | 1 | Information | | 3 | 2 | Support | | 2 | 1 | FAQ | | 3 | 2 | Support | | 2 | 1 | FAQ | | 1 | 1 | Information | | 1 | 1 | Information | +----+--------+-------------+
Однако, как вы можете видеть, информация верна, но есть повторяющиеся строки. Я хотел бы удалить такие дубликаты, поэтому вместо этого использовал SELECT DISTINCT
. Однако это привело к следующему:
+----+--------+-------------+ | id | userid | title | +----+--------+-------------+ | 3 | 2 | Support | | 2 | 1 | FAQ | | 1 | 1 | Information | +----+--------+-------------+
Это, очевидно, неправильно, так как поток «Информация» должен быть сверху. Казалось бы, использование DISTINCT
приводит к удалению дубликатов сверху вниз, поэтому остаются только последние строки. Это вызывает некоторые проблемы при сортировке.
Это так, или я неправильно анализирую ситуацию?
Две вещи, чтобы понять:
Вообще говоря, результаты не упорядочены, если вы не укажете предложение ORDER BY
; в той мере, в которой вы указываете нестрогий порядок (то есть ORDER BY
по неисторическим столбцам), порядок, в котором записи, равные при этом упорядочении, отображаются в наборе результатов, не определен.
Я подозреваю, что вы можете указать такой нестандартный порядок, который является корнем ваших проблем: убедитесь, что ваш заказ является строгим, указав ORDER BY
по набору столбцов, который достаточен для уникальной идентификации каждой записи, для которой вы заботитесь о ее конечная позиция в наборе результатов.
DISTINCT
может использовать GROUP BY
, что приводит к упорядочению результатов по сгруппированным столбцам; то есть SELECT DISTINCT a, b, c FROM t
будет выдавать набор результатов, который выглядит так, как будто ORDER BY a, b, c
. Опять же, указание достаточно строгого порядка для удовлетворения ваших потребностей переопределит этот эффект.
После вашего обновления, имея в виду мою точку № 2 выше, ясно, что эффект группировки результатов для достижения DISTINCT
делает невозможным последующее упорядочение p.id
столбцом p.id
; вместо этого вы хотите:
SELECT t.* FROM Threads t INNER JOIN Posts p ON t.id = p.threadid GROUP BY t.id ORDER BY MAX(p.id) DESC
DISTINCT
информирует MySQL о том, как построить набор строк для вас, ORDER BY
дает подсказку, как этот набор строк должен быть представлен. Итак, ответ: DISTINCT
сначала, ORDER BY
last.
Порядок, в котором применяются DISTINCT
и ORDER BY
, в большинстве случаев не повлияет на окончательный вывод.
Однако, если вы также используете GROUP BY
, это повлияет на окончательный вывод. В этом случае ORDER BY
выполняется после GROUP BY
, который вернет неожиданные результаты (если вы ожидаете, что сортировка будет выполнена до группировки).