Почему один запрос возвращает больше, чем другой

Используя следующий вопрос, не могли бы вы объяснить мне, в чем разница между двумя SQL-запросами и почему они не дают одинаковых результатов?

Отображать фамилию, название отдела и зарплату любого сотрудника, чья зарплата и комиссионные соответствуют зарплате и комиссионным любого сотрудника, расположенного в местоположении ID1700.

SELECT E.LAST_NAME, D.DEPARTMENT_NAME, E.SALARY
  FROM EMPLOYEES E
  JOIN DEPARTMENTS D
    ON (E.DEPARTMENT_ID =D.DEPARTMENT_ID)
  WHERE E.SALARY IN (SELECT SALARY
                       FROM EMPLOYEES
                       WHERE D.LOCATION_ID = 1700) AND
        E.COMMISSION_PCT IN (SELECT COMMISSION_PCT
                               FROM EMPLOYEES
                               WHERE D.LOCATION_ID = 1700);

(0 выходов)

а также

SELECT e.last_name, d.department_name, e.salary
  FROM employees e,
       departments d
  WHERE e.department_id = d.department_id AND
        (salary, NVL(commission_pct,0)) IN (SELECT salary, 
                                                   NVL(commission_pct,0)
                                              FROM employees e,
                                                   departments d
                                              WHERE e.department_id = d.department_id AND
                                                    d.location_id = 1700);

(36 выходов)


person Jey.L    schedule 11.12.2016    source источник
comment
Какую базу данных вы на самом деле используете? Я предполагаю, что Oracle, и я также предполагаю, что это проблема домашнего задания.   -  person Tim Biegeleisen    schedule 11.12.2016
comment
Да, БД Оракл. Я пытаюсь понять, почему 0 не работает. (это я сам написал). Решением вопроса является тот, у которого 36 выходов. Я не знаю, почему SQL, который я набираю, неверен, мне он кажется правильным, но, по-видимому, он не основан на результатах.   -  person Jey.L    schedule 11.12.2016
comment
Добавьте некоторые примеры данных таблицы и два текущих результата. (А также отформатированный текст.) Также покажите нам желаемый результат.   -  person jarlh    schedule 11.12.2016
comment
Это похоже на образцы таблиц и запросов из образцов Oracle SQL. Не могли бы вы опубликовать свои образцы данных, чтобы мы могли воссоздать их?   -  person Migs Isip    schedule 11.12.2016
comment
@MigsIsip — это стандартная схема HR, которая поставляется с каждой установкой Oracle (почти). Если у вас есть доступ к Oracle, у вас должен быть доступ к схеме. (И если вы этого не сделаете, все равно трудно понять, как вы могли бы воссоздать!)   -  person mathguy    schedule 11.12.2016
comment
@mathguy, я всегда использовал среду Oracle EBS, поэтому у меня нет этой схемы в базе данных. :(   -  person Migs Isip    schedule 13.12.2016
comment
@MigsIsip - трудно поверить. Скорее всего, они никогда не были активированы вашим администратором баз данных? Согласно документации (например, docs.oracle.com/cd /E26401_01/doc.122/e22952/T156458T659606.htm) стандартные схемы, в частности HR, включены в EBS.   -  person mathguy    schedule 13.12.2016


Ответы (1)


Обратите внимание, что этот запрос:

SELECT e.last_name, d.department_name, e.salary
  FROM employees e,
       departments d
  WHERE e.department_id = d.department_id AND
        (salary, NVL(commission_pct,0)) IN (SELECT salary, 
                                                   NVL(commission_pct,0)
                                              FROM employees e,
                                                   departments d
                                              WHERE e.department_id = d.department_id AND
                                                    d.location_id = 1700);

... будет включать всех сотрудников, у которых такая же зарплата и комиссионные, что и у человека в местоположении 1700. Следовательно, все сотрудники в местоположении 1700 будут включены в результирующий набор. Но можно найти и других сотрудников, не в том месте, если только в месте 1700 есть кто-то с точно такой же зарплатой и комиссионными. Таким образом, этот запрос правильно отвечает на данное задание.

Однако другой запрос имеет странное условие в обоих подзапросах, поскольку он применяет условие к внешнему запросу (единственное место, где определено D), а не к подзапросу, и делает это дважды (что не помощь):

SELECT E.LAST_NAME, D.DEPARTMENT_NAME, E.SALARY
  FROM EMPLOYEES E
  JOIN DEPARTMENTS D
    ON (E.DEPARTMENT_ID =D.DEPARTMENT_ID)
  WHERE E.SALARY IN (SELECT SALARY
                       FROM EMPLOYEES
                       WHERE D.LOCATION_ID = 1700) AND
        E.COMMISSION_PCT IN (SELECT COMMISSION_PCT
                               FROM EMPLOYEES
                               WHERE D.LOCATION_ID = 1700);

Вы не изменили бы ничего существенного, если бы переместили это условие на location_id во внешнее предложение where. И теперь становится ясно, что этот запрос исключает любых сотрудников, которые не находятся в местоположении 1700 — это не всегда верно для другого запроса.

Кроме того, в этом случае функция NVL не применяется к commission_pct, а это означает, что сотрудники будут исключены также, если у них есть null как commission_pct. Это связано с тем, что NULL IN (SELECT ...) всегда оценивается как false.

Итак, есть две причины, почему этот запрос может вернуть меньше записей, а также почему это неправильный ответ на полученное задание.

person trincot    schedule 11.12.2016
comment
спасибо, сэр, есть ли более простой способ переписать запрос, используя мой метод? Можно ли использовать JOIN? И я действительно не понимаю, что значит. Вы не изменили бы ничего существенного, если бы переместили это условие на location_id во внешнее предложение where. иметь в виду... - person Jey.L; 11.12.2016
comment
Извините, я думал, что ваш вопрос был в чем разница между двумя SQL-запросами и почему они не дают одинаковых результатов?. Теперь вы просите переписать запрос? Если это ваш вопрос, пожалуйста, задайте новый вопрос (нет проблем). Мой комментарий к условию location_id означает, что это условие не относится ни к чему в подзапросе, и поэтому вводит в заблуждение. Это условие внешнего запроса, поэтому его нужно поместить туда. А я говорю, что такой ход не изменит результата. Но это лучше проясняет, что происходит. - person trincot; 11.12.2016