2016-09-22 79 views
1

我有两个表:PostgreSQL表名或别名不指定列名

CREATE TABLE a (id INT NOT NULL); 
CREATE TABLE b (id INT NOT NULL); 
INSERT INTO a VALUES (1), (2); 
INSERT INTO b VALUES (1); 

如果我尝试从a得到记录,其中有在b查询1)记录:

SELECT a.id, b FROM a LEFT JOIN b on a.id = b.id WHERE b is NOT NULL; 

我得到:

id | b 
----+----- 
    1 | (1) 

如果我尝试从a得到记录,其中有在b查询2)没有记录:

SELECT a.id, b FROM a LEFT JOIN b on a.id = b.id WHERE b IS NULL; 

我得到:

id | b 
----+--- 
    2 | 

似乎确定。

然后我改变b

ALTER TABLE b ADD COLUMN s TEXT NULL; 

然后查询1不返回任何行,查询2点返回相同的行和

SELECT a.id, b FROM a LEFT JOIN b on a.id = b.id; 

回报

id | b 
----+------ 
    1 | (1,) 
    2 | 

我的问题是:

  1. 为什么Postresql允许在WHERE子句中使用表名或别名而不指定列名?
  2. 什么是(1,)b产生的行?
  3. 为什么(1,)在查询1和查询2中不满足IS NULLIS NOT NULL

P.S.如果我将表b改为ALTER TABLE b ADD COLUMN s TEXT NOT NULL DEFAULT '',则查询1和2将返回相同的行。

回答

1

回答的问题:

  1. 这行的构造函数,所以从一列中的每个值建立起来,使用您的列值的成员字段
  2. (1,)行值(合成值)是行构造函数的第一个成员是1和第二个成员(您的文本字段),其值为null,因此没有显示值。
  3. 你比较这实际上满足这两个比较(为null与is not null)整行构造

更多关于第3点:

select *, b is not null as b_not_null, b is null as b_null from b; 

Reult:

id | b_not_null | b_null 
----+------------+-------- 
    1 | t   | f 

连续IS NULL当其所有成员都有NULL值时,否则它IS NOT NULL。重现:

create table rowtest (col1 int, col2 int); 
insert into rowtest values (null,null), (1,1), (null,1); 

select 
    col1, col2, rowtest, 
    case when rowtest is null then true else false end as rowtest_null 
from rowtest; 

结果:

col1 | col2 | rowtest | rowtest_null 
------+------+---------+-------------- 
     |  | (,)  | t 
    1 | 1 | (1,1) | f 
     | 1 | (,1) | f 

实际上,对于您的疑问,他们都可以被改写为:

查询1:从a获取记录从b匹配的记录

使用INNER JOIN这实际上是一样的JOIN

SELECT a.id, b FROM a JOIN b on a.id = b.id; 

QUERY2

SELECT a.id 
FROM a 
WHERE NOT EXISTS (
    SELECT 1 
    FROM b 
    WHERE a.id = b.id 
); 

为:从b

使用NOT EXISTS而不是LEFT JOIN获取来自a没有符合条件的记录记录最后一个查询,如果你真的需要第二个空列,你可以添加一个静态值选择列表中那样:

SELECT a.id, null as b 
+0

感谢术语行构造函数。当我试图寻找答案时,我错过了它。请回答问题3添加说明如何测试行是否为IS NULL(所有行的值必须为NULL)和IS NOT NULL(行的所有值必须为NOT NULL)。可能对其他人有用,为两列三行的表添加示例,其中第一行具有全部空值,第二行在第一列中不为空,在第二列中不为空,第三行在两列中都不为空。 – mixel

+0

编辑的答案包括重现和观察将行与'IS NULL'和'IS NOT NULL'进行比较的行为的步骤。 –

+0

当所有成员都有NULL值时,行是NULL,否则它不是NULL - 这是错误的。实际上,只有当它的所有成员都没有空值时,行才是非空的。 – mixel

0

表名可以在SELECTWHERE被用于指含有所述表的整个行中的记录值。在psql的输出中,将出现一条记录,如(1)(如果它有一个字段)或(1,2)(如果它有两个字段)等。您看到的(1,)是包含值为1NULL的两个字段的记录。记录类型的值可以为空,例如在左连接中,如果第二个表没有匹配的行。