2013-11-26 33 views
0

我们有这台产品在商店用这样的价值观:SQL选择的行数,并用相等值的多个行的标识值

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 

正如你可以看到有具有相同名称的产品,而params,但不同的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 

,因为我们是从外部源(web服务)接收的库存数量,每天每个股票更新后几次这个过程是必需的,我们需要评估其应保持活跃。

我们做在这一刻什么和工作正常,但没有一个良好的性能是使用存储过程执行以下操作:

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 

回答

0

我用RANK函数在SQL Server中,并责令在递减,见下面的代码:

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

谢谢!奇迹般有效。只有一个精度,你在RANK()后错过了OVER。 – ramvanet

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