Неожиданный результат предложения NATURAL JOIN и USING - PullRequest
0 голосов
/ 25 ноября 2018

Итак, я учусь получать данные из нескольких таблиц, и у меня есть вопрос, касающийся NATURAL JOIN и предложения USING.Итак, у меня есть 2 таблицы, из которых я извлекаю данные;сотрудники и отделы.

SQL> describe employees 
Name                                      Null?    Type
 ----------------------------------------- -------- ------------------------
 EMPLOYEE_ID                                        NUMBER(6)
 FIRST_NAME                                         VARCHAR2(20)
 LAST_NAME                                 NOT NULL VARCHAR2(25)
 EMAIL                                     NOT NULL VARCHAR2(25)
 PHONE_NUMBER                                       VARCHAR2(20)
 HIRE_DATE                                 NOT NULL DATE
 JOB_ID                                    NOT NULL VARCHAR2(10)
 SALARY                                             NUMBER(8,2)
 COMMISSION_PCT                                     NUMBER(2,2)
 MANAGER_ID                                         NUMBER(6)
 DEPARTMENT_ID                                      NUMBER(4)

SQL> describe departments
 Name                                      Null?    Type
 ----------------------------------------- -------- ------------------------
 DEPARTMENT_ID                             NOT NULL NUMBER(4)
 DEPARTMENT_NAME                                    VARCHAR2(30)
 MANAGER_ID                                         NUMBER(6)
 LOCATION_ID                                        NUMBER(4)

Когда я использую NATURAL JOIN и USING в двух разных выражениях, я получаю два разных вывода.Я знаю, что USING соответствует одному столбцу в обеих таблицах, но как это влияет на вывод?Почему выражение с USING создает одно дополнительное значение по сравнению с NATURAL JOIN?

SELECT department_id, manager_id, last_name, location_id
FROM employees NATURAL JOIN departments
WHERE department_id = 80
ORDER BY location_id desc;

DEPARTMENT_ID MANAGER_ID LAST_NAME                 LOCATION_ID
------------- ---------- ------------------------- -----------
       80        149 Abel                             2500
       80        149 Grant                            2500
       80        149 Taylor                           2500

SELECT department_id, departments.manager_id, last_name, location_id
FROM employees JOIN departments
USING (department_id)
WHERE department_id = 80
ORDER BY location_id desc;

DEPARTMENT_ID MANAGER_ID LAST_NAME                 LOCATION_ID
------------- ---------- ------------------------- -----------
       80        149 Zlotkey                         2500 <-Additional Line*
       80        149 Grant                           2500
       80        149 Taylor                          2500
       80        149 Abel                            2500

Любая помощь и советы приветствуются!

Ответы [ 2 ]

0 голосов
/ 08 января 2019

Мой первый совет - применить принцип «единой ответственности» к вашей схеме.Подумайте о роли / персоне, которая будет обновлять данные и при каких обстоятельствах они будут это делать.Итог: таблица employees несет «слишком большую ответственность».Имя сотрудника и дата найма обычно меняются реже, чем зарплата.Зарплата будет доступна каждый день оплаты.Номер телефона может быть закрытым.Подумайте о создании новых таблиц, разделив таблицу employees на основе обязанностей.

Во-вторых, подумайте о разграничении (а) таблиц, которые моделируют «сущности», таких как сотрудники, и (б) таблиц, которые моделируют отношения междуэти лица.Ваши две таблицы в настоящее время смешивают эти две концепции.Рассмотрим новую таблицу для отношения org char (кто кем управляет) и еще одну таблицу для моделирования отношений между сотрудниками и отделами.

В-третьих, подумайте о том, присваиваете ли вы одному и тому же элементу данных одно и то же имя по всему вашемуНапример, схема может иметь разные значения: «менеджер сотрудника» и «менеджер отдела» (например, в запросах с обоими запросами вы должны переименовать хотя бы один из них, чтобы избежать путаницы).Если это так, рассмотрите возможность сделать имя более явным и не отвечайте на имя таблицы, чтобы указать ее в контексте.

После изменения схемы в соответствии с приведенным выше советом вы, скорее всего, обнаружите, что ваши запросы работают должным образом.TL; DR, если вам трудно писать простой SQL DML, рассмотрите возможность изменения вашего SQL DDL.

0 голосов
/ 25 ноября 2018

Поскольку NATURAL JOIN объединяется во всех столбцах с одинаковыми именами, следовательно, ваш запрос NJ будет также соединяться с manager_id, тогда как форма USING не будет

Если вы изучите форму USING, вы увидите, что manager_idв каждой таблице разные.(Сделайте ваш запрос SELECT *, и вы увидите ..)

При естественном объединении этого различия в manager_id между двумя таблицами удалит строку из результатов

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

Редактировать:

Запустить это:

SELECT *
FROM employees JOIN departments
USING (department_id)
WHERE department_id = 80
ORDER BY location_id desc;

Посмотрите на два столбца, показывающие идентификатор менеджера.Данные в строке Zlotkey будут другими

Вы естественным образом вступили в эффективное объединение, сделав это:

SELECT *
FROM employees e JOIN departments d
on e.department_id = d.department_id AND e.manager_id = d.manager_id
WHERE department_id = 80
ORDER BY location_id desc;

И on e.department_id = d.department_id AND e.manager_id = d.manager_id не верно для строки Zlotkey

Этопочему естественное соединение рискованно и, возможно, бесполезно - просто потому, что два столбца имеют одинаковое имя, не означает, что данные в них связаны между собой.Действительно, в вашем случае в ваших отделах есть менеджеры, а у ваших сотрудников - менеджеры.У меня также есть эта настройка на моей работе, но человек, который является моим менеджером, не является менеджером отдела, в котором я работаю

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...