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"。我在几种情况下对此进行了测试,效果很好。我希望这对遇到同样问题的其他人有所帮助。
我有一个 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"。我在几种情况下对此进行了测试,效果很好。我希望这对遇到同样问题的其他人有所帮助。