简体   繁体   English

SELECT语句中的DB2 SQL合并行

[英]DB2 SQL Merge Rows in SELECT statement

I have the following query for which I would like to merge rows for BusinessPhone, Fax, mobile number, email. 我有以下查询,我想为其合并BusinessPhone,传真,手机号码,电子邮件的行。 At the moment these results are returned on separate lines. 目前,这些结果在单独的行中返回。 How can I achieve this? 我该如何实现?

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')

To solve this one, you get to play games with the joins. 要解决这一问题,您需要玩联接游戏。 To start with, I'm going to make the following assumptions based on your sample query: 首先,我将基于您的示例查询进行以下假设:

  • Your primary key to the F0101 table is the address number (ABAN8). F0101表的主键是地址号(ABAN8)。 It is unique. 它是独一无二的。
  • Each address type ('ST' or 'SC') has its own unique address number (ABAN8). 每种地址类型(“ ST”或“ SC”)都有其自己的唯一地址号(ABAN8)。
  • You only want one row per address number value. 每个地址编号值只需要一行。
  • Phone numbers and email addresses are stored in F0115. 电话号码和电子邮件地址存储在F0115中。 There is a one-to-many relationship between F0101 and F0115. F0101和F0115之间存在一对多关系。
  • Address lines are stored in F0115. 地址行存储在F0115中。 There is a one-to-one relationship between F0101 and F0115. F0101和F0115之间存在一对一的关系。

With the one-to-many relationship between F0101 and F0115, a simple join query results in multiple address records being returned: one for each phone/email record. 通过F0101和F0115之间的一对多关系,简单的联接查询将导致返回多个地址记录:每个电话/电子邮件记录一个。 But if we change the join so that it only returns one row, and do a separate join for each phone type, then we can treat the phone numbers (and email) as separate fields in a single row. 但是,如果我们更改联接以使其仅返回一行,并对每种电话类型进行单独的联接,则可以将电话号码(和电子邮件)视为一行中的单独字段。 So, let's remove the LEFT OUTER JOIN CLTDTA.F0115 ON ABAN8=WPAN8 and replace it with five joins: 因此,让我们删除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

Be aware that some of these joins will fail, returning null values, if there isn't a certain phone type for a certain address. 请注意,如果某个地址没有特定的电话类型,则其中一些连接将失败,并返回空值。 This is normal, expected, and why we use left joins instead of inner joins. 这是正常现象,这是正常现象,这也是为什么我们使用左联接而不是内部联接的原因。

To finish things out, we change out the part of the SELECT clause with all of those CASEs and just replace them with the fields in question, pulling from the appropriate join. 为了解决问题,我们将所有这些CASE替换为SELECT子句的一部分,并从相关联的连接中将它们替换为相关字段。 This is why the table aliases were used in the joins, you have to be able to specify which of the 5 versions of F0115 we want to pull a particular value from: 这就是在联接中使用表别名的原因,您必须能够指定要从以下哪个特定值中提取F0115的5个版本中的哪个:

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

Depending on your application, if returning nulls is a problem, you can wrap each of those WPPH1 fields in an IFNULL() function. 根据您的应用程序,如果返回空值是一个问题,则可以将每个WPPH1字段包装在IFNULL()函数中。 Here is the final query: 这是最终查询:

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')

See jarlh answer in the comments for solution. 请参阅注释中的jarlh答案以获取解决方案。

You have to GROUP BY all selected columns that are not arguments to set functions. 您必须GROUP BY所有不是设置函数参数的选定列。 (And do MAX on the CASE expressions. (并在CASE表达式上执行MAX。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM