SQL选择具有相等值的多行的行数和Id值

时间:2013-11-26 21:17:04

标签: sql sql-server select group-by

我们为商店中的产品提供了此表格,其价值如下:

Id   Name       PartNumber   Param1    Param2    Param3   Stock   Active
--   ---------  ----------   ------    ------    ------   -----   ------
1    BoxA1      10000        20        A         B        4       1
2    BoxA1      10000.a      20        A         B        309     1
3    CabinetZ2  30000        40        B         C        0       0
4    CabinetZ2  30000.b      40        B         C        1098    1
5    BoxA1      10000.c      20        A         B        15      1

如您所见,有些产品具有相同的名称和参数,但ID和部件号不同。

Id为1,2和5的产品具有相同的名称和参数值。

我们需要根据库存禁用相同的param产品,因此我们只有具有相同参数的产品库存更活跃的产品。

结果应该是这样的:

Id   Name       PartNumber   Param1    Param2    Param3   Stock   Active
--   ---------  ----------   ------    ------    ------   -----   ------
1    BoxA1      10000        20        A         B        4       0      <- Not active
2    BoxA1      10000.a      20        A         B        309     1      <- Active 
3    CabinetZ2  30000        40        B         C        0       0
4    CabinetZ2  30000.b      40        B         C        1098    1
5    BoxA1      10000.c      20        A         B        15      0      <- Not active

此过程是必需的,因为我们每天都会多次从外部来源(网络服务)接收库存数量,并且在每次库存更新后,我们需要评估哪些应该保持活动状态。

我们此时所做的工作正常但效果不佳的是使用执行以下操作的存储过程:

DECLARE product_list CURSOR READ_ONLY FORWARD_ONLY LOCAL FOR
  SELECT Id, Name, PartNumber, Param1, Param2, Param3, Stock 
  FROM Products
  ORDER BY Name, Param1, Param2, Param3, Stock DESC

OPEN product_list

FETCH NEXT FROM product_list INTO @OldId, @OldName, @OldPartNumber, @OldParam1, @OldParam2, @OldParam3, @OldStock

WHILE @@FETCH_STATUS <> -1
BEGIN

    (Compare all rows and perform updates to disable the ones with less stock)

    FETCH NEXT FROM product_list INTO @OldId, @OldName, @OldPartNumber, @OldParam1, @OldParam2, @OldParam3, @OldStock

END
CLOSE product_list

使用OVER(PARTITION BY)找到这种类型的查询,我们非常接近于提高效率的目标:

SELECT Id, Name, PartNumber, Param1, Param2, Param3, Stock, Active,
    ROW_NUMBER() OVER (PARTITION BY Name, Param1, Param2, Param3 ORDER BY stock DESC) AS Items
FROM Products

具有以下结果:

Id   Name       PartNumber   Param1    Param2    Param3   Stock   Items
--   ---------  ----------   ------    ------    ------   -----   ------
1    BoxA1      10000        20        A         B        4       3
3    CabinetZ2  30000        40        B         C        0       2

问题在于我们找到了第一个Id,而不是具有更多库存的Id。

我们期待这样的结果,但找不到修复此查询或解决方法的方法:

Id   Name       PartNumber   Param1    Param2    Param3   Stock   Items
--   ---------  ----------   ------    ------    ------   -----   ------
2    BoxA1      10000.a      20        A         B        309     3
4    CabinetZ2  30000.b      40        B         C        1098    2

3 个答案:

答案 0 :(得分:0)

WITH t AS (SELECT ROW_NUMBER() OVER (PARTITION BY Name, Param1, Param2, Param3 ORDER BY stock DESC) i,* FROM Products)
UPDATE t
SET Active = CASE i WHEN 1 THEN 1 ELSE 0 END

你的问题中存在一个含糊不清的问题:如果两个ID在库存中具有相同的#,它们是活动的,还是只有一个?如果只有一个,什么决定优先级?

如果你想要两者都活跃:

WITH t AS (SELECT MAX(stock) OVER (PARTITION BY Name, Param1, Param2, Param3) max_stock,* FROM Products)
UPDATE t
SET Active = CASE WHEN stock = max_stock THEN 1 ELSE 0 END

答案 1 :(得分:0)

我会说这就是你要找的东西。我不确定你为什么需要rownumber()

SELECT * FROM Products p1
INNER JOIN
(SELECT Name, PartNumber, MAX(Stock) AS MaxStock
FROM Products
GROUP BY Name, PartNumber) AS p2
ON p1.Name = p2.Name AND p1.PartNumber = p2.PartNumber AND p1.Stock = p2.MaxStock;

答案 2 :(得分:0)

我在sql server中使用RANK函数并在desc中对它进行排序,请参阅下面的代码:

select Id,
    name,
    partnumber,
    param1,
    param2,
    param3, 
    stock,
    active 
    from (
        select *, 
            RANK() (parition by id, param1, param2, param3 order by stock desc) as max_stock 
            from product)x
        where max_stock = 1