【问题标题】:Select single row with multiple rows in joined table在连接表中选择多行的单行
【发布时间】:2017-07-23 06:12:39
【问题描述】:

我有一个如下的联系表:

contactid | contactname  
----------|-------------
C1        | Name1  
C2        | Name2

我有一张如下的通讯表

contactid | communication_type | communication_string
----------|--------------------|---------------------
C1        | Phone              | 9090909090
C1        | Email              | c1@email.com
C2        | Phone              | 9191919191
C2        | Email              | c1@email.com

现在我的要求是查询这两个表,结果如下:

contactid | contactname | phonenumber   | emailaddress
----------|-------------|---------------|----------------
C1        | Name1       | 9090909090    | c1@email.com
C2        | Name2       | 9191919191    | c2@email.com

如果我做一个常规的加入,就像

SELECT cont.contactid, cont.contactname, 
  comm.communication_type, comm.communication_string 
  FROM contact cont
  LEFT JOIN communication comm ON cont.contactid = comm.contactid 

我会得到类似的东西

contactid | contactname | communication_type| communication_string 
----------|-------------|-------------------|----------------
C1        | Name1       | Phone             | 9090909090
C1        | Name1       | Email             | c1@email.com
C2        | Name2       | Phone             | 9191919191
C2        | Name2       | Email             | c2@email.com

但这不是我想要的。 我希望结果中的通信字符串位于同一行,而不是不同的行。

这有可能得到这样的结果吗?

还有一个要求是解决方案应该通用,以适用于所有数据库。

【问题讨论】:

  • 不要标记每个数据库老兄。现在来吧。这是一个关键问题,他们的做法各不相同。

标签: mysql database oracle postgresql db2


【解决方案1】:

您可以使用条件聚合:

select cont.contactid,
    cont.contactname,
    max(case when comm.communication_type = 'Phone' then comm.communication_string end) PhoneNumber,
    max(case when comm.communication_type = 'Email' then comm.communication_string end) EmailAddress
from contact cont
left join communication comm on cont.contactid = comm.contactid
group by cont.contactid,
    cont.contactname;

这将为给定的contactId返回一个电话号码和电子邮件地址。

此解决方案适用于大多数 RDBMS。

【讨论】:

  • 这对我有用..!谢谢.. 但是,您使用 max 是为了避免 group by 子句还是出于任何其他原因?
  • @Rama - 这是一种常见的旋转技术,即将行转换为列。并非所有数据库都支持PIVOT 子句(mysql 就是其中之一)。
【解决方案2】:

你可以在不同的条件下多次加入同一张表:

select   c.contactid
    ,c.contactname
    ,cp.comunication_string as 'phonenumber'
    ,ce.comunication_string as 'emailaddress'

from    contact c
        left join
        communication cp    on  c.contactid = cp.contactid
                            and cp.comunication_type = 'Phone'
        left join
        communication ce    on  c.contactid = ce.contactid
                            and ce.comunication_type = 'Email'  

标准 SQL 且易于阅读。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 1970-01-01
    • 1970-01-01
    • 2013-02-26
    • 2018-04-15
    • 1970-01-01
    • 2021-01-06
    相关资源
    最近更新 更多