【问题标题】:Recursive CTE in SQL - How to avoid repeated results?SQL 中的递归 CTE - 如何避免重复结果?
【发布时间】:2017-06-09 13:37:42
【问题描述】:

在我的 SQL 数据模型中,我有一个将客户与客户帐户联系起来的关系表。一个账户可以被多个客户持有,一个客户可以持有多个账户。

我想查找客户之间的关系,同时还显示帐户。为此,我创建了一个给定客户编号的 CTE,递归地获取该客户的关系和关系的关系。

例如,假设我有以下数据集:

  • 客户 1,帐户 1
  • 客户 2,账户 1
  • 客户 2,账户 2
  • 客户 3,帐户 2
  • 客户 4,帐户 3

为客户编号 1 运行 CTE,我想获取客户 1、2、3 和帐户 1、2。但是,由于这是递归的,我还要获取每个重复的关系 (1 -> 2 -> 1)达到预设的最大深度。有什么方法可以“标记”现有的关系,使其不会被重复选择?

这是我的 CTE,基于 Microsoft 的 CTE 示例:

WITH EntityRelations(CUSTOMERNUMBER, ACCOUNTID, RELATEDWITH, Level)
AS
(
    SELECT 
        C.CUSTOMERNUMBER, 
        A.ACCOUNTNUMBER, 
        CREL.CUSTOMER related, 
        0 as level
    FROM CUSTOMER_ACCOUNT CA
    INNER JOIN CUSTOMER C
        ON C.ID = CA.CUSTOMERID
    INNER JOIN ACCOUNT A
        ON A.ID = CA.ACCOUNTID
    --Get direct relationships
    LEFT JOIN CUSTOMER_ACCOUNT CREL
        ON CREL.ACCOUNTID = CA.ACCOUNTID
        AND CREL.CUSTOMERID <> CA.CUSTOMERID
    WHERE BCE.CUSTOMER = 1

    UNION ALL
    --Recursion
    SELECT 
        C.CUSTOMERNUMBER, 
        A.ID, 
        CREL.CUSTOMER related, 
        Level+1
    FROM CUSTOMER_ACCOUNT CA
    INNER JOIN CUSTOMER C
        ON C.ID = CA.CUSTOMERID
    INNER JOIN ACCOUNT A
        ON A.ID = CA.ACCOUNTID
    --Get direct relationships
    LEFT JOIN CUSTOMER_ACCOUNT CREL
        ON CREL.ACCOUNTID = CA.ACCOUNTID
        AND CREL.CUSTOMERID <> CA.CUSTOMERID
    INNER JOIN EntityRelations ER
        ON ER.RELATEDWITH = CA.CUSTOMERID
    WHERE Level < 3 --Maximum
)

SELECT * FROM EntityRelations 

【问题讨论】:

标签: sql-server tsql recursion common-table-expression


【解决方案1】:

在您的SELECT 中保留客户的 csv 列表,然后检查新客户是否在列表中。

一个基本的带有idea的伪代码

 SELECT .... , ',' as lstCustomer   -- empty list

 UNION ALL

 SELECT .... ,  customerID || ',' as lstCustomer -- add new customer

 WHERE ',' || lstCustomer || ',' 
       NOT LIKE '%,' || customerID  || ',%'  
                         -- Check if list already have this customer

编辑:我假设您希望限制 CUSTOMER 的出现次数,如果您希望限制 Customer, Account 您可以这样做

 UNION ALL

 SELECT .... ,  '{' || customerID || '-' || accountID || '},' as lstCustomer 
                -- add new customer

 WHERE ',' || lstCustomer || ',' 
       NOT LIKE '%,{' || customerID  || '-' || accountID || '},%'  
                         -- Check if list already have this customer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    • 1970-01-01
    • 2015-06-14
    • 2016-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多