直接相关表或另一个间接相关表中的行匹配条件

问题描述 投票:0回答:1

假设三张表:

create table table_a(  id int generated by default as identity primary key);
create table table_c(  id int generated by default as identity primary key
                     , active boolean);
create table table_b(  id int generated by default as identity primary key
                     , active boolean
                     , table_a_id int references table_a(id)
                     , table_c_id int references table_c(id));

table_a
中的行可以通过
table_c
table_b
中的行相关。
table_c
table_b
各有一个
boolean
属性,称为
active

如何编写 SQL 语句或活动记录表达式来获取每个

table_a
记录

  • 没有关联的
    table_b
    记录显示
    active
    另存为
    true
  • 有一个或多个关联的
    table_b
    记录,但没有一个链接到
    table_c
    行且
    active
    保存为
    true

输入示例:
db<>fiddle 的演示

with populated_a as 
  (insert into table_a values
     (1) --YES, doesn't have a `b` or `c` at all
    ,(2) --NO, has an active `b`
    ,(3) --YES, has a `b` but it's inactive
    ,(4) --NO, has both an active `b` and active `c`
    ,(5) --YES, has an active `b` but it links to an inactive `c`
    ,(6) --YES, has an inactive `b` and it links to an inactive `c`
   returning *)
,populated_c as 
  (insert into table_c values(2,false)
                            ,(3,true)
                            ,(4,true)
                            ,(5,false)
                            ,(6,false)
                            ,(7,true)--no associated `a` or `b`
   returning *)
insert into table_b(active,table_c_id,table_a_id)
values (true,2,2)
      ,(false,3,3)
      ,(true,4,4)--also links to active `c`
      ,(true,5,5)--links to inactive `c`
      ,(false,6,6);

我的尝试:

SELECT "table_a".* FROM "table_a"
LEFT OUTER JOIN "table b"
ON "table_b"."table_a_id" = "table_a"."id"
AND "table_b"."active" = true
LEFT OUTER JOIN "table_c"
ON "table_b"."table_c_id" = "table_c"."id" 
AND "table_c"."active" = true
WHERE "table_b"."id" IS NULL OR "table_c"."id" IS NULL

预期输出是行

(1,3,5,6)
。我的代码返回它们全部,但它也错误地返回
2
,其中有一个活动的
b

sql ruby-on-rails postgresql
1个回答
-1
投票

基本上,我在彼此深处做了两个 LEFT OUTER JOIN,最终按照我的预期工作:

SELECT "table_a".* FROM "table_a"
LEFT OUTER JOIN "table b"
ON "table_b"."table_a_id" = "table_a"."id"
AND "table_b"."active" = true
LEFT OUTER JOIN "table_c"
ON "table_b"."table_c_id" = "table_c"."id" 
AND "table_c"."active" = true
WHERE "table_b"."id" IS NULL OR "table_c"."id" IS NULL
© www.soinside.com 2019 - 2024. All rights reserved.