使用sql / postgresql查询显示带有列名的条件输出

时间:2016-11-11 18:15:13

标签: sql postgresql

我有三张桌子:

1> Table_A
2> Table_B
3> Table_C

Table_A包含以下

id(PK)    ssn
---       ---
1         111
2         222
3         333

Table_B包含以下

id (PK)   ssn   details
----      ---   ------
11        111   hi
22        222   hello
33        555   hi hello
44        666   hi hello hi

Table_C包含以下

id(PK)    ssn  mobile   flag
-----     ---  ------   ----
1X        555  9830     A
2X        555  9831     B
3X        666  9745     A
4X        666  9876     B
5X        777  3454     A
6X        777  8734     B

首先,我需要找到Table_B中存在的SSN,而不是Table_A

中的SSN
select 
distinct b.ssn
from
Table_B b
where
b.ssn not in (select ssn from Table_A)

以上将给我记录

 ssn
 ---
 555
 666

现在我需要从Table_C以下面的方式打印,对应于我上面的ssn(s),

 ssn    to_mobile   from_mobile
 ---    ---------   -----------
 555    9830        9831
 666    9745        9876

即,如果flag为A,则移动列将为to_mobile;如果flag值为B,则移动列将为from_mobile。

我真的无法找到这条出路。请帮助

2 个答案:

答案 0 :(得分:2)

使用left join获取table_b中不在table_a中的值,然后连接table_c并使用条件聚合。

select 
 b.ssn
,max(case when c.flag = 'A' then c.mobile end) to_mobile
,max(case when c.flag = 'B' then c.mobile end) from_mobile
from table_B b
left join table_A a on a.ssn=b.ssn
join table_C c on c.ssn=b.ssn
where a.ssn is null
group by b.ssn

假设每个给定的ssn标志A,B各有一行。

答案 1 :(得分:1)

你可以继续你失败的道路:

select c.ssn,
       max(case when c.flag = 'A' then c.mobile end) as to_mobile,
       max(case when c.flag = 'B' then c.mobile end) as from_mobile
from table_c c
where c.ssn in (select b.ssn
                from Table_B b
                where b.ssn not in (select ssn from Table_A)
               )
group by c.ssn;

也就是说,没有子查询的vkp的答案也是解决此类问题的一种非常典型的方法。

实际上,正如我想的那样,你的条件是c.ssn在B而不是A,所以我会选择:

select c.ssn,
       max(case when c.flag = 'A' then c.mobile end) as to_mobile,
       max(case when c.flag = 'B' then c.mobile end) as from_mobile
from table_c c
where c.ssn in (select b.ssn from Table_B b) and
      c.ssn not in (select a.ssn from Table_A a)
group by c.ssn;

不知何故,我发现这是最容易理解的。