Применяет ли ORDER BY до или после DISTINCT?

В запросе 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 приводит к удалению дубликатов сверху вниз, поэтому остаются только последние строки. Это вызывает некоторые проблемы при сортировке.

Это так, или я неправильно анализирую ситуацию?

Две вещи, чтобы понять:

  1. Вообще говоря, результаты не упорядочены, если вы не укажете предложение ORDER BY ; в той мере, в которой вы указываете нестрогий порядок (то есть ORDER BY по неисторическим столбцам), порядок, в котором записи, равные при этом упорядочении, отображаются в наборе результатов, не определен.

    Я подозреваю, что вы можете указать такой нестандартный порядок, который является корнем ваших проблем: убедитесь, что ваш заказ является строгим, указав ORDER BY по набору столбцов, который достаточен для уникальной идентификации каждой записи, для которой вы заботитесь о ее конечная позиция в наборе результатов.

  2. 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 , который вернет неожиданные результаты (если вы ожидаете, что сортировка будет выполнена до группировки).