使用NOT EXISTS子句查询SELECT语句

时间:2014-05-17 07:21:32

标签: sql database oracle11g sqlplus

表位:

CREATE TABLE Position(
p#              NUMBER(8)       NOT NULL, /* Position number            */
ptitle          VARCHAR(30)     NOT NULL, /* Position title             */
employer    VARCHAR(100)    NOT NULL, /* Institution name           */
salary      NUMBER(9,2) NOT NULL, /* Salary         */
extras      VARCHAR(50)     , /* Extras         */
specification   LONG                , /* Specification      */
    CONSTRAINT Position_pkey PRIMARY KEY ( p# ),
    CONSTRAINT Position_fkey1 FOREIGN KEY ( ptitle )
                REFERENCES LPTitle ( title ) );

INSERT INTO Position VALUES ( 00000001, 'LECTURER', 'UNSW', 45000.00, 'computer', 'Teaching');
INSERT INTO Position VALUES ( 00000002, 'LECTURER', 'UOW', 45000.00, 'mouse pad', 'Research');
INSERT INTO Position VALUES ( 00000003, 'SENIOR LECTURER', 'UTS', 50000.00, NULL, 'A lot of hard work'  );
INSERT INTO Position VALUES ( 00000004, 'ASSOC. PROFESSOR', 'UOW', 60000.00, NULL, NULL);
INSERT INTO Position VALUES ( 00000005, 'PROFESSOR', 'UQ', 80000.00, 'chair', 'Research' );
INSERT INTO Position VALUES ( 00000006, 'PROFESSOR', 'UNSW', 80000.00, 'chair', 'Research' );
INSERT INTO Position VALUES ( 00000007, 'PROFESSOR', 'UOW', 80000.00, 'chair', 'Teaching and research');

我试图找到薪水最高的职位名称。在这种情况下,它应该是' PROFESSOR'。这是我提出的问题:

SELECT DISTINCT
    ptitle
FROM
    Position
WHERE
    NOT EXISTS
        (
            SELECT ptitle FROM Position WHERE salary < (SELECT MAX(salary) FROM Position)
        )
;

我得到的结果是“没有选择行”#39;。当我只运行子查询时,我可以得到除最高薪水位置之外的所有职位名称:

SQL> SELECT ptitle FROM Position WHERE salary < (SELECT MAX(salary) FROM Position);

PTITLE                                                                                              
------------------------------                                                                      
LECTURER                                                                                            
LECTURER                                                                                            
SENIOR LECTURER                                                                                     
ASSOC. PROFESSOR

但每当我在上面的NOT EXISTS查询中将其作为子查询运行时,我无法以最高薪水回到该位置。为什么呢?

3 个答案:

答案 0 :(得分:2)

获得您正在寻找的结果的一种更简单的方法是使用分析函数按工资rank计算所有职位,然后选择最高职位:

SELECT ptitle
FROM   (SELECT ptitle, RANK() OVER (ORDER BY salary DESC) AS rk
        FROM   position)
WHERE  rk = 1

答案 1 :(得分:1)

您的子查询:

SELECT ptitle FROM Position WHERE salary < (SELECT MAX(salary) FROM Position)

始终找到相同的四行,因此始终返回至少一个结果,因此exists始终为真,因此not exists始终为false。您正在检查的行与子查询之间没有相关性。如果你想要一个not exists,那么你需要在子查询中包含主表中的行:

SELECT DISTINCT
    ptitle
FROM
    Position pos1
WHERE
    NOT EXISTS
        (
            SELECT ptitle FROM Position pos2 WHERE pos2.salary > pos1.salary
        )
;

要使用max,您可以检查相等性:

SELECT DISTINCT
    ptitle
FROM
    Position
WHERE
    salary = (SELECT MAX(salary) FROM Position)
;

SQL Fiddle

或者使用分析功能,这样您就不必像其他地方那样打两次表。

答案 2 :(得分:1)

尝试尽可能准确地制定问题几乎总是一个好主意。在这种情况下:

For what positions p1 does it not exist another position p2 such that that position has a 
higher salary.

将其翻译成sql现在很简单:

SELECT distinct ptitle
FROM Position p1
WHERE NOT EXISTS (
    SELECT ptitle FROM Position p2 
    WHERE p2.salary > p1.salary
);

这澄清了吗?