Sql 如何按一组递增列
我有一个名为Sql 如何按一组递增列,sql,sql-server,sql-update,sql-order-by,Sql,Sql Server,Sql Update,Sql Order By,我有一个名为productLocation的表,其数据结构如下: 对于每个位置,都有自己的产品排序顺序。但有些产品将0作为排序值 现在我需要编写一个查询来更新SortValueas 如果我考虑一个位置, fkLoosithId=1 < /代码> +--------------+-------------+-----------+ | FkLocationId | FkProductId | SortValue | +--------------+-------------+----------
productLocation
的表,其数据结构如下:
对于每个位置,都有自己的产品排序顺序。但有些产品将0
作为排序值
现在我需要编写一个查询来更新SortValue
as
如果我考虑一个位置,<代码> fkLoosithId=1 < /代码>
+--------------+-------------+-----------+
| FkLocationId | FkProductId | SortValue |
+--------------+-------------+-----------+
| 1 | 100 | 0 |
+--------------+-------------+-----------+
| 1 | 101 | 0 |
+--------------+-------------+-----------+
| 1 | 102 | 0 |
+--------------+-------------+-----------+
| 1 | 103 | 2 |
+--------------+-------------+-----------+
| 1 | 104 | 1 |
+--------------+-------------+-----------+
| 1 | 105 | 3 |
+--------------+-------------+-----------+
在上面的数据表中,您可以看到,FkProductId=100101102
具有0
作为排序值。我需要按降序将其sortValue
更新为order byFkProductId
。我需要更新它的内容
+--------------+-------------+-----------+
| FkLocationId | FkProductId | SortValue |
+--------------+-------------+-----------+
| 1 | 100 | 3 |
+--------------+-------------+-----------+
| 1 | 101 | 2 |
+--------------+-------------+-----------+
| 1 | 102 | 1 |
+--------------+-------------+-----------+
并逐个更新以前的SortValue
那么完整的输出应该是
+--------------+-------------+-----------+
| FkLocationId | FkProductId | SortValue |
+--------------+-------------+-----------+
| 1 | 100 | 3 |
+--------------+-------------+-----------+
| 1 | 101 | 2 |
+--------------+-------------+-----------+
| 1 | 102 | 1 |
+--------------+-------------+-----------+
| 1 | 103 | 5 |
+--------------+-------------+-----------+
| 1 | 104 | 4 |
+--------------+-------------+-----------+
| 1 | 105 | 6 |
+--------------+-------------+-----------+
这可能吗?我真的很困惑,请帮我解决这个问题。多谢各位
更新:
假设我有另一张桌子作为产品。其数据结构如下:
+-----------+-----------+
| ProdcutId | SortValue |
+-----------+-----------+
| 100 | 0 |
+-----------+-----------+
| 101 | 0 |
+-----------+-----------+
| 107 | 0 |
+-----------+-----------+
| 108 | 1 |
+-----------+-----------+
| 109 | 2 |
+-----------+-----------+
| 110 | 6 |
+-----------+-----------+
| 111 | 5 |
+-----------+-----------+
| 112 | 4 |
+-----------+-----------+
| 113 | 3 |
+-----------+-----------+
我也需要为这张桌子做同样的事情,我该怎么做呢
预期产出:
+-----------+-----------+
| ProdcutId | SortValue |
+-----------+-----------+
| 100 | 3 |
+-----------+-----------+
| 101 | 2 |
+-----------+-----------+
| 107 | 1 |
+-----------+-----------+
| 108 | 4 |
+-----------+-----------+
| 109 | 5 |
+-----------+-----------+
| 110 | 9 |
+-----------+-----------+
| 111 | 8 |
+-----------+-----------+
| 112 | 7 |
+-----------+-----------+
| 113 | 6 |
+-----------+-----------+
下面是一个示例查询,供您使用CTE检查更新过程并使用相同的逻辑-
重要提示:更新是一个危险的过程,您应该首先尝试使用测试数据
WITH CTE
AS
(
SELECT *,
(
SELECT COUNT(*)
FROM #Temp B
WHERE B.FkLocationId = A.FkLocationId
AND SortValue = 0
) Zero_Count,
-- The above Zero count is a simple count of rows with 0
-- for a specific FkLocationId. This is for adding to other
-- rows where there are already value in column SortValue. The logic
-- is simple, the number of row with 0 in column SortValue,
-- should be add to existing value where there is value not equal 0.
ROW_NUMBER() OVER (PARTITION BY FkLocationId ORDER BY SortValue ASC, FkProductId DESC) RN
-- ROW_NUMBER is simply creating the Number you should replace 0 by.
-- As you are looking for 1 to start for the MAX FkProductId with 0,
-- I applied DESC order on that column
FROM #Temp A
)
UPDATE A
SET A.SortValue =
CASE
WHEN A.SortValue = 0 THEN B.RN
-- RN is created in such way, so that you can directly
-- Replace your value in column SortValue by RN if SortValue = 0
ELSE A.SortValue + B.Zero_Count
-- IF SortValue contains already value > 0,
-- You need to just increment the value with Number
-- of rows is there with value 0. I have calculated that value
-- by a sub query in the CTE you can check.
END
FROM #Temp A
INNER JOIN CTE B ON A.FkLocationId = B.FkLocationId
AND A.FkProductId = B.FkProductId
SELECT * FROM #Temp
只要用我用过的“表名”就行了
我所采用的方法的核心是基于行数窗口函数,它将数据按sortvalue和fkproductid降序地划分到fkproductid上
涉及到两个查询,虽然可以通过单个查询完成,但为了简单起见,我使用了公共表表达式(CommonTableExpression,cte)
在第二次更新查询中,从查询一派生的CTE用作联接表
我给自己留下了很多探索的余地,请记住,从集合的角度思考是非常必要的 有一个漂亮的小按钮叫做“文本到DDL”。请使用它,并将您的问题与示例数据一起使用。请向我们展示您的尝试,以便我们能够提供帮助。@ZoharPeled我使用SQL fiddle sir更新了问题@Adam如果确实有用,请接受答案:)如果您能解释查询中的每个部分,会更好。@Adam,我在脚本中添加了一些注释。检查是否有帮助。如果需要进一步澄清,我可以解释。主席先生,我在我的问题中添加了另一个更新的部分。请你解释一下,我如何对该表做同样的事情。所以我很容易接受一个想法。请给我一个更新部分的答案,你也可以使用相同的查询。唯一的区别是这次没有FkLocationId列。只需避免查询中使用FkLocationId列作为ref的部分。
WITH CTE
AS
(
SELECT *,
(
SELECT COUNT(*)
FROM #Temp B
WHERE B.FkLocationId = A.FkLocationId
AND SortValue = 0
) Zero_Count,
-- The above Zero count is a simple count of rows with 0
-- for a specific FkLocationId. This is for adding to other
-- rows where there are already value in column SortValue. The logic
-- is simple, the number of row with 0 in column SortValue,
-- should be add to existing value where there is value not equal 0.
ROW_NUMBER() OVER (PARTITION BY FkLocationId ORDER BY SortValue ASC, FkProductId DESC) RN
-- ROW_NUMBER is simply creating the Number you should replace 0 by.
-- As you are looking for 1 to start for the MAX FkProductId with 0,
-- I applied DESC order on that column
FROM #Temp A
)
UPDATE A
SET A.SortValue =
CASE
WHEN A.SortValue = 0 THEN B.RN
-- RN is created in such way, so that you can directly
-- Replace your value in column SortValue by RN if SortValue = 0
ELSE A.SortValue + B.Zero_Count
-- IF SortValue contains already value > 0,
-- You need to just increment the value with Number
-- of rows is there with value 0. I have calculated that value
-- by a sub query in the CTE you can check.
END
FROM #Temp A
INNER JOIN CTE B ON A.FkLocationId = B.FkLocationId
AND A.FkProductId = B.FkProductId
SELECT * FROM #Temp
with cte as
(select FkLocationId, FkProductId, SortValue,
ROW_NUMBER() over(partition by FkLocationId order by sortvalue,FkProductId desc) new_sort_value
from productLocation where FkLocationId =1 --and SortValue =0
)
update pl SET
pl.SortValue = c.new_sort_value
from productLocation pl inner join cte c
on pl.FkLocationId = c.FkLocationId and pl.FkProductId = c.FkProductId
Select * from productLocation where FkLocationId =1 order by FkProductId