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 by
FkProductId
。我需要更新它的内容

+--------------+-------------+-----------+
| 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