如何使用 CTE 对列进行条件更新?
How to do conditional update on columns using CTE?
我有一个 table CUST
布局如下。没有限制。我确实看到一个 ChildID
与多个 ParentID
相关联。 (请查看 ChildID = 115
的记录)
这是我需要的 -
只要一个 child 超过 1 个 parent,我想用 ParentID
和 [=15= 更新那些 ParentID
和 ParentName
] 最大 match_per
。所以在下图中,我希望 ParentID
1111 和 ParentName
LEE YOUNG WOOK 更新所有 ChildId = 115
的记录(因为 match_per
0.96 在给定的集合中是最大值)。如果有两个 parent 的最大值 match_per 相等,那么我想选择其中的任意一个。
我知道可以使用 CTE,但我不知道如何更新 CTE。有人可以帮忙吗?
一种方法
WITH CTE1 AS
(
SELECT *,
CASE WHEN match_per =
MAX(match_per) OVER (PARTITION BY ChildId)
THEN CAST(ParentId AS CHAR(10)) + ParentName
END AS parentDetailsForMax
FROM CUST
), CTE2 AS
(
SELECT *,
MAX(parentDetailsForMax) OVER (PARTITION BY ChildId) AS maxParentDetailsForMax
FROM CTE1
)
UPDATE CTE2
SET ParentId = CAST(LEFT(maxParentDetailsForMax,10) AS int),
ParentName = SUBSTRING(maxParentDetailsForMax,10,8000)
试试这样的东西??第一个 CTE 将为每个 ChildID 获得 Max(match_per)
。然后,第二个将使用新的 MaxMatchPer 来查找其对应的 ParentID 应该是什么。
; WITH CTE AS (
SELECT ChildID,MAX(match_per) AS MaxMatchPer
FROM tbl
GROUP BY ChildID
), CTE1 AS (
SELECT t.ParentID, c.ChildID
FROM tbl t
JOIN CTE c
ON c.ChildID = t.ChildID
AND c.MaxMatchPer = t.match_per
)
UPDATE t
SET ParentID = c.ParentID
FROM tbl t
LEFT JOIN CTE1 c
ON c.ChildID = t.ChildID
另外,这是很差的归一化。您不应在此 table 中包含 ParentName 或 ChildName。
获取父 ID 和父名称有点棘手。我认为逻辑最简单使用 cross apply
:
with toupdate as (
select t.*, p.parentId as new_parentId, p.parentName as new_parentName
max(match_per) over (partition by childid) as max_match_per,
count(*) over (partition by childid) as numparents
from table t cross apply
(select top 1 p.*
from table p
where p.childid = t.childid
order by match_per desc
) p
)
update toupdate
set parentId = new_ParentId,
parentName = new_ParentName
where numparents > 1;
注意:父 ID 和父名称都存储在 table 中,这可能是一个问题。我希望根据 ID 查找名称,以减少数据冗余。
我有一个 table CUST
布局如下。没有限制。我确实看到一个 ChildID
与多个 ParentID
相关联。 (请查看 ChildID = 115
的记录)
这是我需要的 -
只要一个 child 超过 1 个 parent,我想用 ParentID
和 [=15= 更新那些 ParentID
和 ParentName
] 最大 match_per
。所以在下图中,我希望 ParentID
1111 和 ParentName
LEE YOUNG WOOK 更新所有 ChildId = 115
的记录(因为 match_per
0.96 在给定的集合中是最大值)。如果有两个 parent 的最大值 match_per 相等,那么我想选择其中的任意一个。
我知道可以使用 CTE,但我不知道如何更新 CTE。有人可以帮忙吗?
一种方法
WITH CTE1 AS
(
SELECT *,
CASE WHEN match_per =
MAX(match_per) OVER (PARTITION BY ChildId)
THEN CAST(ParentId AS CHAR(10)) + ParentName
END AS parentDetailsForMax
FROM CUST
), CTE2 AS
(
SELECT *,
MAX(parentDetailsForMax) OVER (PARTITION BY ChildId) AS maxParentDetailsForMax
FROM CTE1
)
UPDATE CTE2
SET ParentId = CAST(LEFT(maxParentDetailsForMax,10) AS int),
ParentName = SUBSTRING(maxParentDetailsForMax,10,8000)
试试这样的东西??第一个 CTE 将为每个 ChildID 获得 Max(match_per)
。然后,第二个将使用新的 MaxMatchPer 来查找其对应的 ParentID 应该是什么。
; WITH CTE AS (
SELECT ChildID,MAX(match_per) AS MaxMatchPer
FROM tbl
GROUP BY ChildID
), CTE1 AS (
SELECT t.ParentID, c.ChildID
FROM tbl t
JOIN CTE c
ON c.ChildID = t.ChildID
AND c.MaxMatchPer = t.match_per
)
UPDATE t
SET ParentID = c.ParentID
FROM tbl t
LEFT JOIN CTE1 c
ON c.ChildID = t.ChildID
另外,这是很差的归一化。您不应在此 table 中包含 ParentName 或 ChildName。
获取父 ID 和父名称有点棘手。我认为逻辑最简单使用 cross apply
:
with toupdate as (
select t.*, p.parentId as new_parentId, p.parentName as new_parentName
max(match_per) over (partition by childid) as max_match_per,
count(*) over (partition by childid) as numparents
from table t cross apply
(select top 1 p.*
from table p
where p.childid = t.childid
order by match_per desc
) p
)
update toupdate
set parentId = new_ParentId,
parentName = new_ParentName
where numparents > 1;
注意:父 ID 和父名称都存储在 table 中,这可能是一个问题。我希望根据 ID 查找名称,以减少数据冗余。