Использование 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 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