【问题标题】:SQL - Identify Customer Line of Business by their Product ColumnSQL - 通过产品列识别客户业务线
【发布时间】:2019-09-22 08:17:28
【问题描述】:

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

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

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

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

投资:经纪、共同基金

人寿保险:人寿保险

我想按客户查看整个表格并说,如果该客户拥有任何银行产品,我想创建一个新列“银行”并在该列中为每一行添加一个“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

这里的逻辑是,银行和投资列有“Y”,因为客户至少有来自每个 LOB 的一种产品。但是,该客户没有人寿保险单,因此该客户的整个列将是“N”。

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

【问题讨论】:

    标签: sql tsql netezza


    【解决方案1】:

    试试这样的:

    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
    

    【讨论】:

      【解决方案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
      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)
      

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

      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)
      

      【讨论】:

      • 对不起,我觉得答案不对。这是我的测试用例:dbfiddle.uk/…
      • 谢谢,我误解了这个问题,我已经相应地更新了我的解决方案
      • @Gen Wan 是的,这两个答案都给了我一组案例陈述给我的东西。我只在该行特定的新列中得到 Y 和 N - 我正在根据每个客户的 Product 列中的所有内容查找 Y 和 N。
      • @EmilySamanthaHeiner 这适用于发布的测试用例。现在我只需要弄清楚如何整合它。初始数据集来自三个表之间的连接,所以我需要使用它来集成...
      • 您可以在 ProductTypes 之前放入另一个 CTE 来对三个表进行初始连接,然后引用它而不是示例中的表变量。如果这有用,请考虑将其标记为正确答案。谢谢!
      【解决方案3】:

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

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

      我使用 CASE 语句为银行、投资和人寿创建适当的列,结果如下:

      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
      

      我通过从按客户编号分组的先前表/结果中执行另一个 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”。我在几种情况下对此进行了测试,效果很好。我希望这可以帮助遇到同样问题的其他人。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-31
        • 2011-08-19
        • 2011-04-28
        • 1970-01-01
        • 2021-08-24
        • 2018-01-24
        • 1970-01-01
        相关资源
        最近更新 更多