postgresql 如何检测每个表中是否存在该值

b1uwtaje  于 2023-04-11  发布在  PostgreSQL
关注(0)|答案(3)|浏览(220)

我想检测每个表中是否存在值
tableA

code value
a    1
b    2
c    3

tableB

code value
a    4
c    5 
d    6

tableC

code value
e    10  
f    11
g    12

我想设置变量。如果我设置像value = 'a'这样的值。我想要的结果如下。
value = a存在于tableA中,因此名为tableA的列被设置为1,而在tableC中,value = a不存在,因此值0被设置。

code tableA tableB tableC valueA valueB valueC
a    1      1      0      1      4      null

我尝试了如下方法,但我不知道如何连接另一个表。

EXISTS (SELECT 1 FROM tableA WHERE code = 'a')

有没有更聪明的方法来实现这一点?如果有人有意见,请让我知道谢谢

liwlm1x9

liwlm1x91#

SelVazis的答案是好的和干净的。然而,如果在任何表中都没有找到值,它将不会返回结果行。如果值在一个或多个表中不止一次,则会返回多个结果行。因此,最好先制作一个响应表并在该响应表中查找答案:

select 
    req.code, 
    resp."tableA", 
    resp."tableB", 
    resp."tableC", 
    resp."valueA", 
    resp."valueB", 
    resp."valueC" 
from 
    (select 'a' as code) req 
left join
    (Select 
        coalesce(codeA, codeB, codeC) as code,
        max(case when codeA is not null then 1 else 0 end) as "tableA",
        max(case when codeB is not null then 1 else 0 end) as "tableB",
        max(case when codeC is not null then 1 else 0 end) as "tableC",
        string_agg(distinct valueA, ', ') as "valueA",
        string_agg(distinct valueB, ', ') as "valueB",
        string_agg(distinct valueC, ', ') as "valueC"
    from 
        (select 
            * 
        from 
            (select code as codeA, value as valueA from tableA) a
        full outer join 
            (select code as codeB, value as valueB from tableB) b 
        on a.codeA = b.codeB
        full outer join 
            (select code as codeC, value as valueC from tableC) c 
        on c.codeC = b.codeB) 
        as subresp 
    group by 
        coalesce(codeA, codeB, codeC)
   ) resp 
   on req.code = resp.code

在本例中,我假设您希望从表中返回所有值,因此我对它们进行了字符串聚合。请随意使用min,max或任何浮动的值来替换它们。
DB fiddle for completeness here

cx6n0qe3

cx6n0qe32#

我可能只是连接你正在寻找的三个数据集。你可以使用伪全外连接(因为没有真实的的连接条件)或聚合的交叉连接来完成这一点:

with a as (select min(value) as val from tablea where code = 'a')
   , b as (select min(value) as val from tableb where code = 'a')
   , c as (select min(value) as val from tablec where code = 'a')
select
  a.val is not null as code_exists_in_a,
  b.val is not null as code_exists_in_b,
  c.val is not null as code_exists_in_c,
  a.val as value_in_a,
  b.val as value_in_b,
  c.val as value_in_c
from a cross join b cross join c;

(For完整的外部连接可以用select code, value as val替换select min(value) as val,用from a full outer join b using (code) full outer join c using (code)替换from a cross join b cross join c)。
免责声明:如果表中的值可以为null,并且您希望将其显示为value exists,但value为null,则必须为此调整上述查询。

oxcyiej7

oxcyiej73#

假设code在每个表上都是唯一的。
你可以使用full outer join来返回所有在left(tableA)或right(tableB)中匹配的记录:

Select coalesce(a.code, b.code, c.code) as code,
  MAX(case when a.code is not null then 1 else 0 end)  as tableA,
  MAX(case when b.code is not null then 1 else 0 end)  as tableB,
  MAX(case when c.code is not null then 1 else 0 end)  as tableC,
  MAX(coalesce(a.value,0))  as valueA,
  MAX(coalesce(b.value,0))  as valueB,
  MAX(coalesce(c.value,0)) as valueC
from tableA a
full outer join TableB b on a.code = b.code
full outer join TableC c on c.code = b.code
where a.code = 'a' or b.code = 'a' or c.code = 'a'
group by coalesce(a.code, b.code, c.code)

或者在full outer join上使用USING而不是ON

Select coalesce(a.code, b.code, c.code) as code,
  case when a.code is not null then 1 else 0 end as tableA,
  case when b.code is not null then 1 else 0 end as tableB,
  case when c.code is not null then 1 else 0 end as tableC,
  coalesce(a.value,0) as valueA,
  coalesce(b.value,0) as valueB,
  coalesce(c.value,0) as valueC
from tableA a
full outer join TableB b using (code)
full outer join TableC c using (code)
where a.code = 'a' or b.code = 'a' or c.code = 'a'

结果:

code    tablea  tableb  tablec  valuea  valueb  valuec
a       1       1       0       1       4       null

Demo here

相关问题