DB2 SQL基于自定义加权从左联接表返回一行

时间:2018-10-03 15:42:42

标签: sql db2 left-join

我有两个表,“ INVOICES”包含发票信息,“ CSEML”包含客户电子邮件地址。电子邮件地址类型(字段EMLTP)可以指定为“ AP”(应付帐款),“ PO”(采购)或空白(默认)。每个客户在CSEML中可以有3个电子邮件地址(每个名称一个)。我希望能够在查询中执行此操作:将发票表加入电子邮件表,并为每张发票最多提取一个电子邮件地址-如果定义了AP地址,则定义了AP地址,否则为默认地址(如果已定义),否则为null。

CSEML的结构如下

CUSTNO,EMLTP,EMAIL
000989367,PO,po@example.com
000254785,PO,po@example3.com
000989367,,default@example.com
000112354,,default@example2.com
000989367,AP,ap@example.com
000254785,,default@example3.com

现在我有以下查询

SELECT I.INVNO, I.CUSTNO, E.EMAIL 
FROM INVOICES I 
LEFT JOIN CSEML E ON I.CUSTNO = E.CUSTNO
WHERE I.INVNO = '10124'

在定义了所有3个地址后,哪个将返回以下内容:

10124    000989367    po@example.com
10124    000989367    default@example.com
10124    000989367    ap@example.com

如何为不同的电子邮件“类型”分配权重,以便仅获得最可取的首选地址?

基于接受的答案的工作代码

SELECT INVNO, CUSTNO, EMAIL
FROM(
    SELECT I.INVNO, I.CUSTNO, E.EMAIL, ROW_NUMBER() OVER (PARTITION BY I.INVNO
        ORDER BY
            CASE WHEN E.EMLTP = 'AP' THEN 0
                 WHEN E.EMLTP = 'PO' THEN 1
                 ELSE 2 END) rn 
    FROM INVOICES I 
    LEFT JOIN CSEML E ON I.CUSTNO = E.CUSTNO
    WHERE I.INVNO = '10124'
) t
WHERE t.rn = 1

2 个答案:

答案 0 :(得分:2)

您可以尝试在此处将ROW_NUMBERCASE表达式一起使用,以对每张发票的电子邮件地址进行排序/优先排序:

SELECT INVNO, CUSTNO, EMAIL
FROM
(
    SELECT I.INVNO, I.CUSTNO, E.EMAIL, ROW_NUMBER() OVER (PARTITION BY I.INVNO
        ORDER BY
            CASE WHEN E.EMAIL LIKE 'ap@%' THEN 0
                 WHEN E.EMAIL LIKE 'po@%' THEN 1
                 ELSE 2 END) rn
    FROM INVOICES I 
    LEFT JOIN CSEML E
        ON I.CUSTNO = E.CUSTNO
    WHERE I.INVNO = '10124'
) t
WHERE t.rn = 1;

答案 1 :(得分:1)

您应该先获取您的首选电子邮件,然后再加入INVOICE或以后。最好的方法可能是CTE或仅是视图。例如

CREATE VIEW CUSTOMER_PREFERED_EMAIL AS
SELECT CUSTNO
,      COALESCE((MAX(CASE WHEN EMLTP = 'AP' THEN EMAIL END))
               ,(MAX(CASE WHEN EMLTP = 'PO' THEN EMAIL END))
               ,(MAX(CASE WHEN EMLTP = ''   THEN EMAIL END))
               ) AS PREFERED_EMAIL
FROM   CSEML E
GROUP BY
        CUSTNO

给出了下表和数据

CREATE TABLE CSEML(CUSTNO int, EMLTP CHAR(2), EMAIL VARCHAR(32));
INSERT INTO  CSEML VALUES 
 (000989367,'PO','po@example.com'     )
,(000254785,'PO','po@example3.com'    )
,(000989367,'','default@example.com'  )
,(000112354,'','default@example2.com' )
,(000989367,'AP','ap@example.com'     )
,(000254785,'','default@example3.com' )
;

将返回

 CUSTNO PREFERED_EMAIL
 ------ --------------------
 989367 ap@example.com
 112354 default@example2.com
 254785 po@example3.com

然后您可以将该视图加入所需的任何内容