Я пытаюсь понять разницу между следующими вопросами - PullRequest
1 голос
/ 06 мая 2020

У меня есть продавец и таблица клиентов, и я пытаюсь найти всех продавцов, которые живут в любом из городов, в которых живет покупатель (обратите внимание, что покупатель связан с конкретным продавцом c, но пока мы просто сравнивают город)

СОЗДАНИЕ ТАБЛИЦЫ (ORACLE)

CREATE TABLE SALESMAN (  
    SALESMAN_ID INT CONSTRAINT SALESMAN_PK PRIMARY KEY,  
    NAME VARCHAR2(15),  
    CITY VARCHAR2(10),  
    COMMISSION DECIMAL(4,2))
;

INSERT ALL  
    INTO SALESMAN VALUES(5001,'JAMES HOOG','NEW YORK',0.15)  
    INTO SALESMAN VALUES(5002,'NAIL KNITE','PARIS',0.13)  
    INTO SALESMAN VALUES(5005,'PIT ALEX','LONDON',0.11)  
    INTO SALESMAN VALUES(5006,'MC LYON','PARIS',0.14)  
    INTO SALESMAN VALUES(5003,'LAUSON HEN','SAN JOSE',0.12)  
    INTO SALESMAN VALUES(5007,'PAUL ADAM','ROME',0.13)  
SELECT * FROM DUAL
;

CREATE TABLE CUSTOMER (   
    CUSTOMER_ID INT CONSTRAINT CUSTOMER_PK PRIMARY KEY,   
    CUST_NAME VARCHAR2(15),   
    CITY VARCHAR(10),   
    GRADE INT,   
    SALESMAN_ID INT,  
    CONSTRAINT FK_CUSTOMER_SALESMAN  
    FOREIGN KEY (SALESMAN_ID) REFERENCES SALESMAN (SALESMAN_ID)) 
;

INSERT ALL   
    INTO CUSTOMER VALUES (3002, 'NICK RIMANDO', 'NEW YORK', 100, 5001)   
    INTO CUSTOMER VALUES (3007, 'BRAD DAVIS', 'NEW YORK', 200, 5001)   
    INTO CUSTOMER VALUES (3005, 'GRAHAM ZUSI', 'CALIFORNIA', 200,5002)   
    INTO CUSTOMER VALUES (3008, 'JULIAN GREEN', 'LONDON', 300,5002)   
    INTO CUSTOMER VALUES (3004, 'FABIAN JOHSON', 'PARIS',300,5006)   
    INTO CUSTOMER VALUES (3009, 'GEOFF CAMEROON', 'BERLIN', 100,5003)   
    INTO CUSTOMER VALUES (3003, 'JOZY ALTIDOR', 'MOSCOW', 200,5007)   
    INTO CUSTOMER VALUES (3001, 'BRAD GUZAN', 'LONDON',NULL,5005)   
SELECT * FROM DUAL
;

SELECT * FROM SALESMAN;

SALESMAN_ID       NAME  CITY    COMMISSION
5001         JAMES HOOG NEW YORK    .15
5002         NAIL KNITE PARIS       .13
5005          PIT ALEX  LONDON      .11
5006          MC LYON   PARIS       .14
5003        LAUSON HEN  SAN JOSE    .12
5007          PAUL ADAM ROME        .13

SELECT * FROM CUSTOMER;

CUSTOMER_ID       CUST_NAME      CITY      GRADE    SALESMAN_ID
3002            NICK RIMANDO    NEW YORK    100       5001
3007             BRAD DAVIS     NEW YORK    200       5001
3005             GRAHAM ZUSI    CALIFORNIA  200       5002
3008            JULIAN GREEN    LONDON      300       5002
3004           FABIAN JOHSON    PARIS       300       5006
3009           GEOFF CAMEROON   BERLIN      100       5003
3003            JOZY ALTIDOR    MOSCOW      200       5007
3001            BRAD GUZAN      LONDON       -        5005

# EXPECTED OUTPUT
SALESMAN_ID    NAME     CITY      COMMISSION
5001        JAMES HOOG  NEW YORK    .15
5006         MC LYON    PARIS       .14
5005        PIT ALEX    LONDON      .11
5002       NAIL KNITE    PARIS      .13

# QUERY 1

SELECT DISTINCT
SLS.*
FROM SALESMAN SLS, CUSTOMER CUST
WHERE SLS.CITY = CUST.CITY

# QUERY 2
SELECT * FROM SALESMAN SLS  
WHERE EXISTS (SELECT SALESMAN_ID FROM CUSTOMER WHERE SLS.CITY = CUSTOMER.CITY)

# QUERY 3
SELECT * FROM SALESMAN SLS  
WHERE SLS.SALESMAN_ID IN  (SELECT DISTINCT CUST.SALESMAN_ID FROM CUSTOMER CUST WHERE SLS.CITY = CUST.CITY)
;

# OUTPUT FROM QUERY 3
SALESMAN_ID      NAME       CITY    COMMISSION
5001         JAMES HOOG   NEW YORK  .15
5006        MC LYON        PARIS    .14
5005        PIT ALEX      LONDON    .11

В трех приведенных выше запросах запрос 1 и 2 дает ожидаемый результат, однако запрос 3 не предоставляет ожидаемый результат. Все запросы имеют одно и то же соединение между городом из таблицы продавца и клиента, но я не понимаю, почему запрос 3 дает другой результат.

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

Обновление

На основании комментариев правильная форма третьего запроса должна просто проверять, существует ли город продавца в таблице клиентов:

SELECT * FROM SALESMAN SLS  
WHERE SLS.CITY IN  (SELECT DISTINCT CITY FROM CUSTOMER CUST)

Это дает те же результаты, что и первые два запроса.

Демо на dbfiddle

Исходный ответ

Причина, по которой ваш третий запрос дает разные результаты, заключается в том, что подзапрос только возвращает значения идентификатора продавца, которые существуют в customer для каждого из городов в salesman, в данном случае это 5001, 5005 и 5006. Таким образом, вы не получите NAIL KNITE на выходе, поскольку ни один из клиентов в Париже, Лондоне или Нью-Йорке была ГВОЗДЬ как продавец.

1023 * Обратите внимание, что это можно утверждать, что запрос 3 на самом деле возвращает правильный результат, как и другие ваши запросы не считают, имеет ли данный продавец любых клиентов в любом городе. Таким образом, ваши два других запроса действительно должны быть:

Запрос 1:

SELECT DISTINCT
SLS.*
FROM SALESMAN SLS
JOIN CUSTOMER CUST ON SLS.CITY = CUST.CITY AND SLS.SALESMAN_ID = CUST.SALESMAN_ID
ORDER BY SLS.SALESMAN_ID

Запрос 2:

SELECT * FROM SALESMAN SLS  
WHERE EXISTS (SELECT * FROM CUSTOMER WHERE SLS.CITY = CUSTOMER.CITY AND CUSTOMER.SALESMAN_ID = SLS.SALESMAN_ID)
ORDER BY SALESMAN_ID

С этими изменениями все три запроса дают одинаковый результат :

SALESMAN_ID     NAME        CITY        COMMISSION
5001            JAMES HOOG  NEW YORK    .15
5005            PIT ALEX    LONDON      .11
5006            MC LYON     PARIS       .14

Демонстрация на dbfiddle

0 голосов
/ 06 мая 2020

В третьем запросе вам не хватает join, и вы ожидаете, что он будет работать так же, как и ваш второй запрос. Вот ваш третий запрос с join.

SELECT * FROM SALESMAN SLS  
WHERE SLS.SALESMAN_ID 
IN  (
      SELECT 
        DISTINCT CUST.SALESMAN_ID 
      FROM CUSTOMER CUST 
      JOIN SALESMAN_ID SLS
      ON SLS.CITY = CUST.CITY
    )

EXISTS намного быстрее, чем IN, когда результаты подзапроса очень большие, и IN намного быстрее, чем EXISTS, когда подзапрос - результатов запроса очень мало.

...