Использование distinct в столбце и выполнение order by в другом столбце дает ошибку

у меня есть таблица: abc_test со столбцами n_num, k_str.

этот запрос не работает:

    select distinct(n_num) from abc_test order by(k_str)

но это работает:

    select n_num from abc_test order by(k_str)

как DISTINCT и ORDER по ключевым словам работают внутренне, что вывод обоих запросов изменяется?

10 ответов


насколько я понял из вашего вопроса .

distinct : - означает выбор distinct (все выбранные значения должны быть уникальными). заказать по : - просто означает заказать выбранные строки в соответствии с вашим требованием .

проблема в вашем первом запросе Например : У меня есть столик!--3-->

ID name
01 a
02 b
03 c
04 d 
04 a

сейчас запрос select distinct(ID) from table order by (name) путается, какую запись он должен взять для ID-04 (так как есть два значения,D и A в столбце Name). Таким образом, проблема для DB engine вот когда вы говорите заказа (имя).........


вы можете подумать об использовании group by вместо:

select n_num
from abc_test
group by n_num
order by min(k_str)

первый запрос невозможно. Давайте объясним это на примере. у нас есть такой тест:

n_num k_str
2     a
2     c
1     b

select distinct (n_num) from abc_test is

2
1

Select n_num from abc_test order by k_str is

2
1
2

что вы хотите вернуть

select distinct (n_num) from abc_test order by k_str?

он должен возвращать только 1 и 2, но как их заказать?


вы выбираете коллекцию distinct (n_num) из результирующего набора из вашего запроса. Таким образом, фактической связи со столбцом k_str больше нет. N_num может быть из двух строк, каждая из которых имеет разное значение для k_str. Таким образом, вы не можете заказать коллекцию distinct(n_num) по k_str.


согласно стандартам SQL, a SELECT предложение может ссылаться как на предложения ("псевдонимы") на верхнем уровне SELECT предложение или столбцы resultset по порядковой позиции,и, следовательно, nether ваших запросов будет соответствовать.

похоже, Oracle, как и другие SQL-имплеметации, позволяет ссылаться на столбцы, которые существовали (логически) непосредственно перед тем, как быть спроецированными в SELECT предложения. Я не уверен, что такая гибкость такая хорошая вещь: IMO рекомендуется предоставить порядок сортировки вызывающему приложению, включив столбец / выражения и т. д. В SELECT предложения.

как всегда, вам нужно применить dsicpline для получения значимых результатов. Для вашего первого запроса определение порядка потенциально полностью произвольно.Вы должны быть благодарны за ошибку;)


этот подход доступен в SQL server 2000, Вы можете выбрать различные значения из таблицы и заказать по другому столбцу, который не включен в Distinct. Но в SQL 2012 это будет через вас ошибка "Если указан параметр SELECT DISTINCT, в списке выбора должны отображаться элементы ORDER BY."

Итак, если вы хотите использовать ту же функцию, что и SQL 2000, Вы можете использовать номер столбца для заказа(это не рекомендуется в лучшей практике).

select distinct(n_num) from abc_test order by 1

Это приказ первый столбец после получения результата. Если вы хотите, чтобы заказ был сделан на основе другого столбца, отличного от distinct, вы должны добавить этот столбец также в инструкции select и использовать номер столбца для заказа.

select distinct(n_num), k_str from abc_test order by 2

как выполнять расширенную сортировку ключевых столбцов

на логический порядок операций в SQL для вашего первого запроса, это (упрощенный):

  • FROM abc_test
  • SELECT n_num, k_str т. е. добавить так называемый расширенный столбец ключа сортировки
  • ORDER BY k_str DESC
  • SELECT n_num т. е. удалить расширенный столбец ключа сортировки снова от результата.

благодаря стандарту SQL расширенный столбец ключа сортировки особенность, можно заказать что-то, чего нет в SELECT предложение, потому что оно временно добавляется к нему за кулисами до заказа, а затем удаляется снова после заказа.

Итак, почему это не работает с DISTINCT?

если мы добавляем DISTINCT операция, ее нужно было бы добавить между SELECT и ORDER BY:

  • FROM abc_test
  • SELECT n_num, k_str т. е. добавить so называется расширенный столбец ключа сортировки
  • DISTINCT
  • ORDER BY k_str DESC
  • SELECT n_num т. е. удалить расширенный столбец ключа сортировки снова от результата.

С расширенный столбец ключа сортировки k_str семантика DISTINCT операция была изменена, поэтому результат больше не будет таким же. Это не то, что мы хотим, поэтому как стандарт SQL, так и все разумные базы данных запрещать такое использование.

решения

PostgreSQL имеет DISTINCT ON синтаксис, который можно использовать здесь именно эту работу:

SELECT DISTINCT ON (k_str) n_num
FROM abc_test
ORDER BY k_str DESC

его можно эмулировать со стандартным синтаксисом следующим образом, если вы не используете PostgreSQL

SELECT n_num
FROM (
  SELECT n_num, MIN(k_str) AS k_str
  FROM abc_test
  GROUP BY n_num
) t
ORDER BY k_str

или, просто (в данном случае)

SELECT n_num, MIN(k_str) AS k_str
FROM abc_test
GROUP BY n_num
ORDER BY k_str

я написал в блоге о SQL DISTINCT и порядке более подробно здесь.


вы пробовали это?

SELECT DISTINCT n_num as iResult
FROM abc_test 
ORDER BY iResult

можно сделать

select distinct top 10000 (n_num)  --assuming you won't have more than 10,000 rows                
from abc_test order by(k_str)

когда я получил ту же ошибку, я разрешил ее, изменив ее как

SELECT n_num 
FROM(
   SELECT DISTINCT(n_num) AS n_num, k_str
   FROM abc_test
) as tbl
ORDER BY tbl.k_str