检查多个表中是否存在一组值

时间:2019-06-05 12:24:52

标签: sql postgresql

我想知道更好的方法来检查一组值是否是另一个值的子集。

由于某种原因,我无法使IN正常工作,所以我使用了类似的方法:

-- check if `table1.id` is in other tables
SELECT (
  -- check if all `table1.id` is in table2's `table1_id`
  ARRAY(SELECT id FROM table1) <@ ARRAY(SELECT table1_id FROM table2)
    AND
  -- check if all `table1.id` is in table3's `table1_id`
  ARRAY(SELECT id FROM table1) <@ ARRAY(SELECT table1_id FROM table3)
  -- ...and so on
)

例如,如果我在table1上有这两行:

+----+
| id |
+----+
|  1 |
|  2 |
+----+

table2上的这两行:

+----+-----------+
| id | table1_id |
+----+-----------+
|  1 |         1 |
|  2 |         2 |
+----+-----------+

这一行在table3

+----+-----------+
| id | table1_id |
+----+-----------+
|  1 |         2 |
+----+-----------+

结果将为false,因为table3不同时包含line_id1中的2

但是,如果table3如下所示:

+----+-----------+
| id | table1_id |
+----+-----------+
|  1 |         2 |
|  2 |         1 |
+----+-----------+

它将返回true

我的方法已经很好了吗?如果我正确使用IN,会更快吗?还有其他我完全想不到的方式吗?

2 个答案:

答案 0 :(得分:1)

您可以只使用内部联接并计算结果:

with table1_count as (
  select count(*) as count
  FROM table1
),
all_table_count as (
  select count(*) as count
    from (
    select table1.id from table1
    join table2 on table1.id = table2.table1_id
    join table3 on table1.id = table3.table1_id
  ) sub
)
select table1_count.count = all_table_count.count as ids_everywhere
from all_table_count,table1_count
;
 ids_everywhere
----------------
 f
(1 row)

加入将比数组比较快得多。

答案 1 :(得分:0)

使用exists

select t1.*
from Table1 t1
where exists (select 1 from table2 t2 where t2.table1_id = t1.id)
and   exists (select 1 from table3 t3 where t3.table1_id = t1.id)
and   exists (select 1 from table4 t4 where t4.table1_id = t1.id)

您还可以使用case语句中存在的内容

select t1.id, 
       case
         when exists (select 1 from table2 t2 where t2.table1_id = t1.id)
           and exists (select 1 from table3 t3 where t3.table1_id = t1.id)
           and exists (select 1 from table4 t4 where t4.table1_id = t1.id)
           then 1
         else 0
       end
from Table1 t1

或列出每个单独的(编辑):

select t1.id,
       case
           when exists (select 1 from table2 t2 where t2.table1_id = t1.id) 
               then 1 else 0
           end as in_tab2,
       case 
           when exists (select 1 from table3 t3 where t3.table1_id = t1.id) 
               then 1 else 0 
           end as in_tab3,
       case 
           when exists (select 1 from table4 t4 where t4.table1_id = t1.id) 
               then 1 else 0 
           end as in_tab4
from table1