【问题标题】:I am trying to understand the difference between the following queruies我试图了解以下查询之间的区别
【发布时间】:2020-08-20 20:31:23
【问题描述】:

我有一个销售人员和一个客户表,我正在尝试查找居住在客户居住的任何城市的所有销售人员(请注意,客户与特定的销售人员相关联,但现在我们只是比较城市)

创建表(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 没有提供预期的输出。所有查询在 salesman 和 customer 表中的 city 之间都有相同的连接,但我不明白为什么查询 3 会给出不同的输出。

【问题讨论】:

    标签: sql oracle join subquery aggregate


    【解决方案1】:

    更新

    基于cmets,第三个查询的正确形式应该只是检查客户表中是否存在销售员所在的城市:

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

    这给出了与前两个查询相同的结果。

    Demo on dbfiddle

    原答案

    您的第三个查询给出不同结果的原因是子查询only返回customersalesman 中每个城市的推销员ID 值,在本例中为5001 , 5005 和 5006。所以你不会在输出中得到 NAIL KNITE,因为巴黎、伦敦或纽约的客户都没有 NAIL 作为推销员。

    请注意,查询 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
    

    Demo on dbfiddle

    【讨论】:

    • 尼克,感谢您的回复。关于您对查询 1 和 2 建议的修改,我明白了,但我并没有试图实现这一点。换句话说,我想要所有的推销员如果任何客户与推销员居住在同一个城市,则提供的信息。所以,我期待查询 1 和 2 给出的输出。对于查询 3,我假设它通常复制来自客户和城市的内部连接推销员。在这种情况下,我的假设是查询应该选择推销员 5002,因为我们有一位住在巴黎的客户。如果我遗漏了什么,请告诉我。
    • @siva 好的,这样就更清楚了。在这种情况下,您的第三个查询无法工作,因为它对 salesman_id 和 city 进行了有效连接,而不仅仅是 city。请参阅我的编辑以获取将执行您在评论中解释的查询
    • 尼克,谢谢你的建议。不知道为什么我没想到:) 顺便说一句,原来的第三个查询只有城市的连接,对吗?子查询是否暗示连接也与 salesman_id 一起发生?我询问第三个查询的主要原因是我很想知道查询实际发生了什么..
    • 原来的第三个查询也有效地与 salesman_id 结合,因为您使用了 salesman_id in (select salesman_id ...) - 这就是为什么我的新查询只使用 city in (select city ...)
    【解决方案2】:

    在第三个查询中,您缺少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快很多,当子查询结果很小时INEXISTS快很多。

    【讨论】:

      猜你喜欢
      • 2017-07-26
      • 1970-01-01
      • 2018-02-21
      • 1970-01-01
      • 1970-01-01
      • 2020-10-29
      • 2019-06-08
      • 1970-01-01
      • 2013-07-15
      相关资源
      最近更新 更多