使用 CTE 中的产品层次结构按用户 ID 删除行

Delete rows by user ID using product hierarchy in CTE

我有一个 table,其中包含数十万个用户 ID 和产品代码。我在 WHILE 循环中使用 CTE 脚本根据层次结构删除产品 ID——即如果用户有产品 18 和 19,我删除 19。如果用户有 17、18 和 19,我删除 18 和 19。问题是循环太昂贵和耗时,无法用于生产 table s.

产品 ID 不是有序的——它们只是 ID。我的目标是根据下面代码中显示的层次结构删除产品 ID 行——例如如果用户 1 存在 17,则删除产品 18 和 19(如果其中一个或两个都存在)。如果产品 18 和 19 存在(例如用户 1),则仅删除 19,留下产品 18。

在下面的示例中,需要保留组中的最低编号,但情况并非总是如此,因此我不能简单地对产品类型进行分组并保留 MIN。

在下面的快速示例中,用户 1 应保留 18,用户 2 应保留 17。相反,只保留用户 2,用户 1 的两个产品都被删除。我不知道我错过了什么.

CREATE TABLE #tmp (
    ID varchar(1),
    Prod varchar(2)
)
INSERT INTO #tmp
VALUES ('1', '18')
      ,('1', '19')
      ,('2', '17')
      ,('2', '18')
      ,('2', '19')

--SELECT * FROM #tmp ORDER BY ID

;WITH CTE (ID, Prod)
        AS
        (SELECT ID, Prod FROM #tmp)
        DELETE FROM CTE
        WHERE (Prod = 19
            AND EXISTS (SELECT t.Prod
                        FROM #tmp t
                            INNER JOIN CTE ON t.ID = cte.ID 
                                AND t.Prod = CTE.Prod
                        WHERE t.Prod = 18
                        ))
        OR  (Prod = 18
            AND EXISTS (SELECT t.Prod
                        FROM #tmp t
                            INNER JOIN CTE ON  t.ID = cte.ID
                                AND t.Prod = CTE.Prod
                        WHERE t.Prod = 17   
                        ))

您的“EXISTS”查询几乎可以归结为“table 中是否有任何 18 位”和“table 中是否有任何 17 位”,它们都是正确的,所以所有19s 和 18s 将被删除。

我想你想要这个

;WITH CTE (ID, Prod) AS (SELECT ID, Prod FROM #tmp)
DELETE FROM CTE
WHERE (Prod = 19 AND EXISTS (SELECT * FROM #tmp t WHERE Prod = 18 AND t.ID = CTE.ID))
OR  (Prod = 18 AND EXISTS (SELECT * FROM #tmp t WHERE Prod = 17 AND t.ID = CTE.ID))