SELECT语句中的DB2 SQL Merge Rows

时间:2016-02-09 09:55:26

标签: sql db2 ibm-midrange db2-400

我有以下查询,我想合并BusinessPhone,传真,手机号码,电子邮件的行。目前,这些结果在不同的行上返回。我怎样才能做到这一点?

SELECT DISTINCT
ABAN8 as AddressNumber,
(CASE WHEN TRIM(ALADD2)!='' THEN CONCAT(CONCAT(TRIM(ALADD1),', '),(CASE WHEN     TRIM(ALADD3)!='' THEN CONCAT(CONCAT(TRIM(ALADD2),', '),(CASE WHEN TRIM(ALADD4)!='' THEN CONCAT(CONCAT(TRIM(ALADD3),', '), TRIM(ALADD4)) ELSE TRIM(ALADD3) END)) ELSE TRIM(ALADD2) END)) ELSE TRIM(ALADD1) END) AS Address,
TRIM(ALCTY1) as City,
TRIM(ALCOUN) as Country,
TRIM(ALADDZ) as PostCode,
TRIM(ABALPH) as Company,
TRIM(WWATTL) as JobTitle,
TRIM(WWGNNM) as FirstName,
TRIM(WWSRNM) as Surname,
CASE WHEN WPPHTP = 'COM' THEN WPPH1 END BusinessPhone,
CASE WHEN WPPHTP = 'FACS' THEN WPPH1 END AS FAX,
CASE WHEN WPPHTP = 'MOB' THEN WPPH1 END AS MobileNumber,
CASE WHEN WPPHTP = 'HOME' THEN WPPH1 END AS HomePhone,
CASE WHEN WPPHTP = 'EML' THEN WPPH1 END AS EmailAddress
FROM CLTDTA.F0101 
LEFT OUTER JOIN CLTDTA.F0111 ON ABAN8 = WWAN8 
LEFT OUTER JOIN CLTDTA.F0115 ON ABAN8 = WPAN8
LEFT OUTER JOIN CLTDTA.F0116 ON ABAN8 = ALAN8
WHERE 
(CLTDTA.F0101.ABAT1 = 'ST' OR CLTDTA.F0101.ABAT1 = 'SC')

2 个答案:

答案 0 :(得分:1)

要解决这个问题,你可以用连接玩游戏。首先,我将根据您的示例查询做出以下假设:

  • 您的F0101表的主键是地址编号(ABAN8)。它很独特。
  • 每种地址类型('ST'或'SC')都有自己唯一的地址编号(ABAN8)。
  • 每个地址编号值只需要一行。
  • 电话号码和电子邮件地址存储在F0115中。 F0101和F0115之间存在一对多的关系。
  • 地址行存储在F0115中。 F0101和F0115之间存在一对一的关系。

通过F0101和F0115之间的一对多关系,简单的连接查询会返回多个地址记录:每个电话/电子邮件记录一个。但是,如果我们更改连接以便它只返回一行,并为每种手机类型执行单独的连接,那么我们可以将电话号码(和电子邮件)视为单行中的单独字段。那么,让我们在ABAN8 = WPAN8上删除LEFT OUTER JOIN CLTDTA.F0115并将其替换为五个连接:

LEFT OUTER JOIN CLTDTA.F0115 ON ABAN8 = WPAN8 AND WPPHTP = 'COM' AS COM115
LEFT OUTER JOIN CLTDTA.F0115 ON ABAN8 = WPAN8 AND WPPHTP = 'FACS' AS FAX115
LEFT OUTER JOIN CLTDTA.F0115 ON ABAN8 = WPAN8 AND WPPHTP = 'MOB' AS MOB115
LEFT OUTER JOIN CLTDTA.F0115 ON ABAN8 = WPAN8 AND WPPHTP = 'HOME' AS HOME115
LEFT OUTER JOIN CLTDTA.F0115 ON ABAN8 = WPAN8 AND WPPHTP = 'EML' AS EML115

请注意,如果某个地址没有特定的电话类型,其中某些连接将失败,返回空值。这是正常的,预期的,以及为什么我们使用左连接而不是内部连接。

为了完成这项工作,我们用所有这些CASE更改了SELECT子句的一部分,只需将它们替换为相应的字段,从适当的连接中取出。这就是为什么表连接在连接中使用的原因,你必须能够指定我们想从中提取特定值的F0115的5个版本中的哪一个:

COM115.WPPH1 AS BusinessPhone,
FACS115.WPPH1 AS FAX,
MOB115.WPPH1 AS MobileNumber,
HOME115.WPPH1 AS HomePhone,
EML115.WPPH1 AS EmailAddress

根据您的应用程序,如果返回null是一个问题,您可以将每个WPPH1字段包装在IFNULL()函数中。这是最终查询:

SELECT DISTINCT
    ABAN8 as AddressNumber,
    (CASE WHEN TRIM(ALADD2)!='' THEN CONCAT(CONCAT(TRIM(ALADD1),', '),(CASE WHEN     TRIM(ALADD3)!='' THEN CONCAT(CONCAT(TRIM(ALADD2),', '),(CASE WHEN TRIM(ALADD4)!='' THEN CONCAT(CONCAT(TRIM(ALADD3),', '), TRIM(ALADD4)) ELSE TRIM(ALADD3) END)) ELSE TRIM(ALADD2) END)) ELSE TRIM(ALADD1) END) AS Address,
    TRIM(ALCTY1) as City,
    TRIM(ALCOUN) as Country,
    TRIM(ALADDZ) as PostCode,
    TRIM(ABALPH) as Company,
    TRIM(WWATTL) as JobTitle,
    TRIM(WWGNNM) as FirstName,
    TRIM(WWSRNM) as Surname,
    IFNULL(COM115.WPPH1) AS BusinessPhone,
    IFNULL(FACS115.WPPH1) AS FAX,
    IFNULL(MOB115.WPPH1) AS MobileNumber,
    IFNULL(HOME115.WPPH1) AS HomePhone,
    IFNULL(EML115.WPPH1) AS EmailAddress
FROM CLTDTA.F0101 
LEFT OUTER JOIN CLTDTA.F0111 ON ABAN8 = WWAN8 
LEFT OUTER JOIN CLTDTA.F0115 ON ABAN8 = WPAN8 AND WPPHTP = 'COM' AS COM115
LEFT OUTER JOIN CLTDTA.F0115 ON ABAN8 = WPAN8 AND WPPHTP = 'FACS' AS FAX115
LEFT OUTER JOIN CLTDTA.F0115 ON ABAN8 = WPAN8 AND WPPHTP = 'MOB' AS MOB115
LEFT OUTER JOIN CLTDTA.F0115 ON ABAN8 = WPAN8 AND WPPHTP = 'HOME' AS HOME115
LEFT OUTER JOIN CLTDTA.F0115 ON ABAN8 = WPAN8 AND WPPHTP = 'EML' AS EML115
LEFT OUTER JOIN CLTDTA.F0116 ON ABAN8 = ALAN8
WHERE (CLTDTA.F0101.ABAT1 = 'ST' OR CLTDTA.F0101.ABAT1 = 'SC')

答案 1 :(得分:-2)

请参阅解决方案评论中的jarlh回答。

  

您必须GROUP BY所有选定的列,这些列不是设置函数的参数。 (并在CASE表达式上执行MAX。