获取最高库存的记录

时间:2018-01-19 15:32:36

标签: sql sql-server

我有3个表项目,地点和股票。

Items 
ItemId   ItemName
444      Item-1
555      Item-2
666      Item-3

Locations
LocationId  LocationName
12           Loc1
13           Loc2
14           Loc3
15           Loc4
17           Loc5


Stock
Id          ItemId       LocationId    stock
1           444           12            2
2           444           13            15
3           555           14            20
4           666           15            14
5           666           17            12

我需要针对每件商品获取1条记录,这些商品的库存最高。 我想要像这样的结果。

Result Table
ItemName        LocationName        stock
Item-1            Loc2               15
Item-2            Loc3               20
Item-3            Loc4               14

目前我正在使用以下查询。

Select I.ItemName,L.LocationName,S.stock from Items I
inner join Stock S on 
I.ItemId = S.ItemId
inner join Locations L on 
S.LocationId = L.LocationId

2 个答案:

答案 0 :(得分:0)

在ANSI-SQL-98中,您首先要从库存表中找出每个项目的最大库存水平,然后重新连接以查找整行中的信息。从那里开始加入将ID转换为名称等的正常情况

SELECT
  *
FROM
(
  SELECT itemId, MAX(stock) AS stock FROM stock GROUP BY itemId
)
  max_stock
INNER JOIN
  stock
    ON  stock.itemId = max_stock.itemId
    AND stock.stock  = max_stack.stock
INNER JOIN
  locations
    ON locations.LocationId = stock.LocationId
INNER JOIN
  Items
    ON items.ItemId = stock.ItemId

在ANSI-SQL-2003中,您可以获得ROW_NUMBER()RANK()等窗口函数...

SELECT
  *
FROM
(
  SELECT
    stock.*,
    RANK() OVER (PARTITION BY itemId
                     ORDER BY stock DESC
                )
                   AS stock_level_rank
  FROM
    stock
)
  ranked_stock
INNER JOIN
  locations
    ON locations.LocationId = ranked_stock.LocationId
INNER JOIN
  Items
    ON items.ItemId = ranked_stock.ItemId
WHERE
  ranked_stock.stock_level_rank = 1

RANK()的一个功能是可以将多行绑定到第一位。所以你不能总是每件商品获得一排。但是,如果两个地点的库存水平完全相同,那么它们都不应该被退回吗?这取决于您的要求。

如果 必须 只有一行,那么最好选择其他列/表达式,以便每次确定性地返回相同的结果。

    ROW_NUMBER() OVER (PARTITION BY itemId
                           ORDER BY stock DESC,
                                    id DESC
                )
                   AS stock_level_rank

在这种情况下,id更高的行会使行更多"优先"在领带的情况下选择的那个。这没有任何意义 真的 ,但至少你总是得到相同输入的相同结果。

答案 1 :(得分:0)

with cte as 
(  select itemID, locationID, stock  
        , row_number() over (partition by itemID order by stock desc) as rn 
   from stock  
)  
select * 
from cte 
join items i 
  on i.itemID = cte.itemID  
 and cte.rn = 1  
join locations l 
  on l.LocationId = cte.LocationId