我有一张表如下:
这是此选择的结果:
http://localhost/users?fields=id,email&expand=profileAge
现在,我想要做的是:对于每个SELECT ParentID, ID, [Default], IsOnTop, OrderBy
FROM [table]
WHERE ParentID IN (SELECT ParentID
FROM [table]
GROUP BY ParentID
HAVING SUM([Default]) <> 1)
ORDER BY ParentID
组,将其中一行设置为默认值(ParentID
),其中使用此逻辑选择行:
如果组有一行[Default] = 1
,则取此行,否则按IsOnTop = 1
排序前1行。
关于如何在SQL中执行此操作,我完全无能为力,我有超过40个这样的组,因此我想请求您的帮助,最好是对您的查询进行一些解释。
答案 0 :(得分:3)
只需在每个ParentID
组中分配一个行号,即可稍微修改当前查询。行号分配的排序逻辑是IsOnTop
值为1的记录首先出现,然后OrderBy
列确定位置。我更新CTE的条件是只有每个ParentID
组中的第一条记录被指定为Default
值为1。
WITH cte AS (
SELECT ParentID, ID, [Default], IsOnTop, OrderBy,
ROW_NUMBER() OVER (PARTITION BY ParentID
ORDER BY IsOnTop DESC, OrderBy) rn
FROM [table]
WHERE ParentID IN (SELECT ParentID FROM [table]
GROUP BY ParentID HAVING SUM([Default]) <> 1)
)
UPDATE cte
SET [Default] = 1
WHERE rn = 1;
答案 1 :(得分:2)
可能会有更快的方法,但这就是我要做的。 首先创建一个CTE
首先,我们根据IsOnTop = 1创建一个CTE,在其中我们在ParentID上添加一个row_number。否则,它会根据OrderBy列选择第一行。
然后我们使用rownumber 1更新行。
WITH FindSoonToBeDefault AS (
SELECT ParentID, ID, [Default], IsOnTop, OrderBy, row_number() OVER(PARTITION BY ParentID ORDER BY IsOnTop DESC, [OrderBy] ASC) AS [rn]
FROM [table]
WHERE ParentID IN (SELECT ParentID
FROM [table]
GROUP BY ParentID
HAVING SUM([Default]) <> 1)
ORDER BY ParentID
)
UPDATE FindSoonToBeDefault
SET [Default] = 1
WHERE [rn] = 1
在屏幕截图中,第12行将是默认值。 第13行不会。
答案 2 :(得分:0)
(1-IsOnTop)*OrderBy
将IsOnTop
和OrderBy
合并到一个结果中,该结果可以排名,以便最低值是您想要的值。使用派生表来确定每个ParentID
的最低结果,然后JOIN
来确定您的默认值。
UPDATE [table]
SET [Default] = 1
FROM [table]
INNER JOIN
(
SELECT ParentID, MIN((1-IsOnTop)*OrderBy) DefaultRank
FROM [table]
GROUP BY ParentID
) AS rankForDefault
ON rankForDefault.ParentID=[table].ParentID
AND rankForDefault.DefaultRank=(1-[table].IsOnTop)*[table].OrderBy