PSQL除了与全部除外

时间:2017-04-25 00:08:47

标签: sql postgresql

我有以下架构:

create table Took(
sID integer,
oID integer,
grade integer);



INSERT INTO Took VALUES
    (1, 1, 90),
    (1, 2, 100),
    (2, 1, 90),
    (2, 3, 80),
    (2, 4, 85)
;

我也有以下查询:

(select sid from took) except all (select sid from took where grade < 90);

并且这产生了预期的输出1,1,2,因为在这种情况下等级值>≥90。但是,当我将all子句删除到

select sid from took) except (select sid from took where grade < 90);

输出只是1。我知道all确定是否存在重复项,所以在这种情况下我希望输出为1,2而不仅仅是1。最近怎么回事?

1 个答案:

答案 0 :(得分:3)

从PSQL文档中,单独使用EXCEPT时:

  

EXCEPT运算符计算左SELECT语句结果中的行集,但不计算右结果的结果。

但是,当ALL与EXCEPT一起使用时:

  

除非指定了ALL选项,否则EXCEPT的结果不包含任何重复的行。对于ALL,在左表中具有m个重复项且在右表中具有n个重复项的行将在结果集中出现max(m-n,0)次。

在您的示例中,左SELECT查询的结果将是所有行的sid。

test=# select sid from took;
 sid
-----
   1
   1
   2
   2
   2
(5 rows)

并且,右SELECT查询的结果将是最后两行,其等级<90。

test=# select sid from took where grade < 90;
 sid
-----
   2
   2
(2 rows)

现在,仅使用EXCEPT:

运行查询
test=# (select sid from took) except (select sid from took where grade < 90);
 sid
-----
   1
(1 row)

这里发生了什么,

  1. 我们采用了左SELECT查询(5行)的结果。
  2. 然后,删除包含右SELECT查询结果的所有匹配行(即sid = 2),我们留下2行,sid = 1.
  3. 现在,由于没有重复,所以最终结果将是1行,sid = 1。
  4. 这是你得到的结果的解释。

    现在,使用EXCEPT ALL运行查询:

    test=# (select sid from took) except all (select sid from took where grade < 90);
     sid
    -----
       1
       1
       2
    (3 rows)
    

    在这种情况下,我们只是从SELECT SELECT查询结果中删除右SELECT查询的结果。

    希望,这有帮助。