我有两张桌子:
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
(查询2 )中没有记录的b
获取记录:
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 |
我的问题是:
WHERE
子句中使用表名或别名而不指定列名?(1,)
列中的b
是什么?(1,)
在查询1和查询2中不满足IS NULL
和IS NOT NULL
? P.S。如果我将表b
改为ALTER TABLE b ADD COLUMN s TEXT NOT NULL DEFAULT ''
,则查询1和2会返回相同的行。
答案 0 :(得分:1)
回答问题:
(1,)
是一个行构造函数,第一个成员为1
,第二个成员(您的文本字段)的值为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;
查询2 :从a
获取与b
无匹配记录的记录
使用NOT EXISTS
代替LEFT JOIN
:
SELECT a.id
FROM a
WHERE NOT EXISTS (
SELECT 1
FROM b
WHERE a.id = b.id
);
对于最后一个查询,如果你真的需要第二个空列,你可以添加一个静态值来选择列表:
SELECT a.id, null as b
答案 1 :(得分:0)
表名可以在SELECT
或WHERE
中使用,以引用包含表格整行的记录值。在psql
的输出中,记录将显示为(1)
(如果它有一个字段),或(1,2)
(如果它有两个字段),等等。(1,)
您会看到包含值1
和NULL
的两个字段的记录。记录类型的值可以为null,例如如果第二个表没有匹配的行,则在左连接中。