SQL - 按产品列识别客户业务线

SQL - Identify Customer Line of Business by their Product Column

我有一个 table,其中包含客户信息 - 他们的客户编号、产品等。我想根据每个客户拥有的产品来确定他们属于哪个业务线。每个客户可以有 1 行或多行(每行表示一个客户及其产品)。它看起来像这样:

Customer #  Product
-----------------------------------------   
000000001   BROKERAGE   
000000001   CHECKING
000000001   CREDIT CARD 
000000001   SAVING
000000001   LIFE INSURANCE  

现在,这只是一个客户,但我有关于哪些产品属于哪些业务线的规则,例如:

银行:支票、信用卡、储蓄

投资:经纪、共同基金

人寿保险:人寿保险

我想做的是按客户查看整个 table,然后说,如果这个客户拥有任何银行产品,我想创建一个新列 "Bank" 并放一个 "Y" 在故事中客户所拥有的每一行的该列中 - 这会告诉我,无论我正在查看哪一行,该客户都是银行客户。最后,我想要一个包含所有这些 LOB 的列,因此最终产品将如下所示:

Customer #  Product          Bank    Investments    Life
---------------------------------------------------------
000000002   BROKERAGE          Y          Y           N
000000002   CHECKING           Y          Y           N
000000002   CREDIT CARD        Y          Y           N
000000002   SAVING             Y          Y           N

这里的逻辑是 Bank 和 Investment 列有 "Y",因为客户至少有来自每个 LOB 的一个产品。但是,该客户没有人寿保险单,因此该客户的整个列将为 "N".

显然,我有多个客户,所以我试图用一个案例语句来做到这一点,但我使用的是只查看当前行的列,所以我只得到 "Y" 其中那一行匹配。我想要匹配该客户的任何行...我想也许可以用 PARTITION 或 GROUP BY 做一些事情,但我不知道从哪里开始...有什么想法或提示吗?

尝试这样的事情:

SELECT tbl.customer, tbl.product,
case when temp.Bank>0 then 'Y' else 'N' end as Bank,
case when temp.Investment>0 then 'Y' else 'N' end as Investment,
case when temp.Insurance>0 then 'Y' else 'N' end as Insurance
FROM tbl
LEFT JOIN
(SELECT customer,
sum(case when Product in ('CHECKING', 'CREDIT CARD', 'SAVINGS') then 1 else 0 end) as Bank, 
sum(case when Product in ('BROKERAGE','MUTUAL FUNDS') then 1 else 0 end) as Investment,
sum(case when Product in ('LIFE INSURANCE') then 1 else 0 end) as Insurance
FROM tbl
GROUP BY Customer) tmp
on tmp.customer=tbl.customer

这应该可以做到...快速、简单、快速的解决方案。

DECLARE @Products table
(
        CustomerNumber int
    ,   Product nvarchar(50)
)

INSERT @Products VALUES (1, 'BROKERAGE')
INSERT @Products VALUES (1, 'CHECKI[NG')
INSERT @Products VALUES (1, 'CREDIT CARD')
INSERT @Products VALUES (2, 'SAVINGS')
INSERT @Products VALUES (2, 'LIFE INSURANCE')


;WITH
ProductTypes AS
(
    SELECT
            CustomerNumber
        ,   SUM(CASE WHEN Product IN ('CHECKING', 'CREDIT CARD', 'SAVINGS') THEN 1 ELSE 0 END) AS Bank
        ,   SUM(CASE WHEN Product IN ('BROKERAGE', 'MUTUAL FUND') THEN 1 ELSE 0 END) AS Investments
        ,   SUM(CASE WHEN Product IN ('LIFE INSURANCE') THEN 1 ELSE 0 END) AS Life
    FROM    @Products
    GROUP BY CustomerNumber
)
SELECT
        Products.CustomerNumber
    ,   Products.Product
    ,   CASE WHEN Bank > 0 THEN 'Y' ELSE 'N' END AS Bank
    ,   CASE WHEN Investments > 0 THEN 'Y' ELSE 'N' END AS Investments
    ,   CASE WHEN Life > 0 THEN 'Y' ELSE 'N' END AS Life
FROM    @Products AS Products
LEFT JOIN ProductTypes ON (ProductTypes.CustomerNumber = Products.CustomerNumber)

此版本已经过修改,以考虑到您正在执行初始连接以获取源的评论 table。

DECLARE @Customer table
(
        CustomerNumber int
)

INSERT @Customer VALUES (1)
INSERT @Customer VALUES (2)

DECLARE @Products table
(
        CustomerNumber int
    ,   Product nvarchar(50)
)

INSERT @Products VALUES (1, 'BROKERAGE')
INSERT @Products VALUES (1, 'CHECKI[NG')
INSERT @Products VALUES (1, 'CREDIT CARD')
INSERT @Products VALUES (2, 'SAVINGS')
INSERT @Products VALUES (2, 'LIFE INSURANCE')


;WITH
CustomerProducts AS
(
    SELECT
            Customer.CustomerNumber
        ,   Products.Product
    FROM @Customer AS Customer
    LEFT JOIN @Products AS Products ON (Products.CustomerNumber = Customer.CustomerNumber)
)
, ProductTypes AS
(
    SELECT
            CustomerNumber
        ,   SUM(CASE WHEN Product IN ('CHECKING', 'CREDIT CARD', 'SAVINGS') THEN 1 ELSE 0 END) AS Bank
        ,   SUM(CASE WHEN Product IN ('BROKERAGE', 'MUTUAL FUND') THEN 1 ELSE 0 END) AS Investments
        ,   SUM(CASE WHEN Product IN ('LIFE INSURANCE') THEN 1 ELSE 0 END) AS Life
    FROM    CustomerProducts
    GROUP BY CustomerNumber
)
SELECT
        CustomerProducts.CustomerNumber
    ,   CustomerProducts.Product
    ,   CASE WHEN Bank > 0 THEN 'Y' ELSE 'N' END AS Bank
    ,   CASE WHEN Investments > 0 THEN 'Y' ELSE 'N' END AS Investments
    ,   CASE WHEN Life > 0 THEN 'Y' ELSE 'N' END AS Life
FROM    CustomerProducts
LEFT JOIN ProductTypes ON (ProductTypes.CustomerNumber = CustomerProducts.CustomerNumber)

虽然上面的两个解决方案很有帮助,但最终我要寻找的解决方案要简单得多。我发现 post 描述了类似的问题,建议的解决方案是在该列上使用 MAX(),按 ID/user/whatever 分组。所以,如果我有以下内容:

Customer #  Product
----------------------------   
000000001   BROKERAGE   
000000001   CHECKING
000000001   CREDIT CARD 
000000001   SAVING
000000001   LIFE INSURANCE 
000000002   BROKERAGE   
000000002   LIFE INSURANCE 

我使用 CASE 语句为 Bank、Investments 和 Life 创建了相应的列,结果如下:

Customer #  Product          Bank    Investments    Life
---------------------------------------------------------
000000001   BROKERAGE          N          Y           N
000000001   CHECKING           Y          N           N
000000001   CREDIT CARD        Y          N           N
000000001   SAVING             Y          N           N
000000002   BROKERAGE          N          Y           N
000000002   LIFE INSURANCE     N          N           Y

所以,现在我知道基于哪些行,该产品属于哪个 LOB,但因为我只想要每个客户所属的 LOB 的摘要 (Y/N)。在这种情况下,我知道客户 #1 是 Bank and Investments 的一部分(该客户至少拥有 Bank and Investments 的一种产品)。客户 #2 只有投资和人寿保险,但没有银行产品。所以,我想看:

Customer #  Bank    Investments    Life
---------------------------------------------------------
000000001     Y          Y           N
000000002     N          Y           Y

我通过从先前的 table/result 中按客户 # 分组执行另一个 SELECT,根据需要对每个 Y/N 列执行 MAX:

SELECT CUST_NUMBER,
MAX(BANK) AS BANK,
MAX(INVENTMENTS) AS INVESTMENTS,
MAX(LIFE) as LIFE
FROM
( ORIGINAL QUERY TO GET PRIOR TABLE
  GROUP BY CUST_NUMBER
) A
ON CUST_NUMBER = A.CUST_NUMBER

如果与该客户编号相关的任何行的每一列都存在 Y,这将为您提供 Y。如果全部"Y",则得到一个"Y",如果至少有1个"Y",则得到一个"Y"。如果该客户的列是该列中所有值的 "N",您将得到 "N"。我在几种情况下对此进行了测试,效果很好。我希望这对遇到同样问题的其他人有所帮助。