DB2 SQL возвращает одну строку из левой объединенной таблицы на основе пользовательского веса - PullRequest
0 голосов
/ 03 октября 2018

У меня есть две таблицы: «Счета-фактуры» содержит информацию о счете-фактуре, а «CSEML» - адреса электронной почты клиентов.Тип адреса электронной почты (поле EMLTP) может быть обозначен как «AP» (Расчеты с поставщиками), «PO» (Закупки) или пустой (по умолчанию).Каждый клиент может иметь 3 адреса электронной почты в CSEML (по одному для каждого назначения).Я хотел бы иметь возможность сделать это в запросе: присоединить таблицу счетов-фактур к таблице электронной почты и извлечь максимум один адрес электронной почты на счет-фактуру - адрес AP, если он определен, в противном случае адрес PO, если он определен,в противном случае адрес по умолчанию, если он определен, иначе ноль.

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 голосов
/ 03 октября 2018

Сначала вы должны получить предпочитаемый адрес электронной почты, а затем присоединиться к 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

, и затем вы сможете присоединить это представление к тому, что вам нужно

0 голосов
/ 03 октября 2018

Вы можете попробовать использовать ROW_NUMBER здесь с выражением CASE, чтобы упорядочить / расставить приоритеты адресов электронной почты каждого счета:

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;
...