查询哪里NOT NULL,但只有当没有用作FK

问题描述 投票:0回答:4
area
-----
id           BIGSERIAL PRIMARY KEY
deleted_at   TIMESTAMP WITH TIME ZONE   DEFAULT NULL

registration
-----
area_id   BIGINT   REFERENCES area(id) NOT NULL

我想从area具有deleted_at IS NULL所有记录,并且可以有deleted_at is NOT NULL但存在作为registration一个FK的人。

SELECT * FROM area
  JOIN registration AS reg 
    ON reg.area_id=area.id
 WHERE area.deleted_at IS NULL;

将省略area记录这是在registration FKS但都被标记为“已删除”。

添加关于AND子句中的列deleted_atJOIN ON条款没有任何意义,因为它只会去掉有效记录。

我不能完全将其套在我的头上,因为这两个where条件那种相互矛盾。

postgresql postgresql-9.6
4个回答
1
投票

尝试是这样的:

SELECT *
  FROM area
    LEFT JOIN registration AS reg ON reg.area_id = area.id
  WHERE (area.deleted_at IS NULL) <> (reg.area_id IS NOT NULL)

LEFT JOIN会列出所有area行,即使没有registration匹配的行。 (对于这些行所得NULL值)。 该WHERE条款可以确保两个领域都没有在同一时间NULLs。


1
投票

我觉得这是你要求的。当您使用左加入它的注册数据字段将显示为空在那里他们没有出现在报名表中。

select * from area
left join registration as reg
on reg.area_id= area.id
where area.deleted_at is null or reg.area_id is not null;

1
投票
-- I need (0) all area records EXCEPT the ones where (1) deleted_at IS NOT NULL
-- AND (2) are NOT present as FKs in registration.

SELECT * FROM area a
WHERE NOT(
   a.deleted_at IS NOT NULL -- (1)
   AND NOT EXISTS (
        SELECT *                -- (2)
        FROM registration r 
        WHERE r.area_id=a.id
        )
     );

注意:你的文字措辞是混乱:EXCEPT a AND b可能意味着两件事


而且,问题的改述后:


-- I want to get (0) all records from area (1) which have deleted_at IS NULL (1a)
-- and (2) the ones that can have deleted_at is NOT NULL but are present as a FK in the registration.

SELECT * FROM area a
WHERE a.deleted_at IS NULL -- (1)
   OR a.deleted_at IS NOT NULL AND EXISTS (                (1a)  
        SELECT *                -- (2)
        FROM registration r 
        WHERE r.area_id=a.id
        );

如果我理解正确的话,你的意思是加在那些(1A):如果是这样,和(1a)中被转换成一个或


0
投票

你只需搜索以下查询?

SELECT * FROM Area
LEFT OUTER JOIN registration on id = area_id
WHERE deleted_at IS NULL OR area_id IS NOT NULL

这将在同一area.id多次返回,如果registration.area_id不是唯一的,虽然(因为你没有UNIQUE约束)。 如果这是一个问题,您可能希望下面的查询来代替。

SELECT * FROM Area
WHERE deleted_at IS NULL OR id IN (SELECT area_id FROM registration)

还是这个,有COUNT内置:

SELECT id, deleted_at, COUNT(*) FROM Area
LEFT OUTER JOIN registration on id = area_id
WHERE (deleted_at IS NULL or area_id IS NOT NULL)
GROUP BY id, deleted_at
© www.soinside.com 2019 - 2024. All rights reserved.