Если вы ищете самую высокую зарплату среди всех сотрудников , которые также имеют некоторую (т.е. не null
) комиссию , то ваш исходный запрос (с удалением .
удаляется):
select * from emp where sal = (select max(sal) from emp) and comm is not null;
делает неправильные вещи. Внутренний select
находит самую высокую зарплату всех сотрудников (независимо от того, имеют ли они также комиссионные) и затем выбирает все записи, соответствующие той зарплате, с которой do имеет комиссионные. Со следующими тестовыми данными:
insert into emp (ename,job,hiredate,sal,comm) values
('a','a','a',100,null),
('b','b','b',200,22),
('c','c','c',300,33),
('d','d','d',400,null) ;
внутренний select
вернет 400
(самый высокий из всех окладов), а внешний select
ничего не вернет, потому чтоединственная запись с этой зарплатой имеет комиссию null
.
Может возникнуть соблазн переместить предложение and comm is not null
в первый оператор select
:
select * from emp where sal = (select max(sal) from emp where comm is not null) ;
, и это вернет3|a|a||a|300|33|
- самая высокая зарплата среди всех сотрудников с некоторыми комиссионными. Однако, это, вероятно, не то, что нужно. Если мы добавим еще одного сотрудника с самой высокой зарплатой и ненулевой комиссией:
insert into emp (ename,job,hiredate,sal,comm) values ('x','x','x',400,44);
, то он вернет обе записи с этой зарплатой:
4|d|d||d|400||
5|x|x||x|400|44|
Мы может восстановить тест comm is not null
во внешнем select
(таким образом, это происходит дважды), но есть лучший способ:
select empno, ename, job, mgr, hiredate, max(sal), comm, deptno from emp where comm is not null ;
, который вернет только одну запись (с оригинальными тестовыми данными):
3|c|c||c|300|33|
и одним с расширенными тестовыми данными:
5|x|x||x|400|44|
(я решил указать поля явно, какобычно считается, что это лучше, чем использование *
. Однако select *, max(sal) ...
также производит аналогичный эффект, хотя он дублирует поле sal
).
Во многих (большинстве?) диалектах SQL выне может смешивать агрегатные функции (например, MAX
) с неагрегированными значениями. Однако SQLite разрешает это, и - где используется MIN
или MAX
- гарантирует, что любые неагрегированные значения будут поступать из одной и той же строки. С Примечание: Голые столбцы в агрегатных запросах в документации SQLite:
Специальная обработка происходит, когда агрегатная функция имеет значение min () или max (). Пример:
SELECT a, b, max(c) FROM tab1 GROUP BY a;
Когда агрегатные функции min () или max () используются в агрегированном запросе, все пустые столбцы в наборе результатов получают значения из входной строки, которая такжесодержит минимум или максимум. Таким образом, в приведенном выше запросе значение столбца «b» в выходных данных будет значением столбца «b» во входной строке с наибольшим значением «c». По-прежнему существует неоднозначность, если две или несколько входных строк имеют одинаковое минимальное или максимальное значение или если запрос содержит более одной агрегатной функции min () и / или max (). Только встроенные функции min () и max () работают таким образом.
(Неоднозначность заключается в , для которых из строк принимаются неагрегированные значения; IЯ практически уверен, что в другом месте говорится, что все они будут из одной строки .