简体   繁体   中英

Greatest N Per Group with Joins: Getting Wrong Max/Min Values

Sadly, another variation on the popular "Greatest-N-Per-Group" query, but it's been kicking my butt and I could really use some clarity (problem simplified as much as possible):

I've got two tables:

Items
-----
ItemID 
ProductName


Inventory
---------
InventoryID
ItemID
Condition
Price

And I'm trying to formulate a query which shows the InventoryID, ItemID, ItemName, Condition, and Max prices for each item In a Given Condition

ie given

Inventory
---------
InventoryID  ItemID  Condition   Price
INV123       ITEM001 NEW         $3.99
INV001       ITEM001 NEW         $3.79
INV031       ITEM001 USED        $1.23
INV234       ITEM001 USED        $1.99

And Items:

ItemID    ItemName
ITEM001   Lg Widget
ITEM002   Sm Widget

I'd Expect:

ItemID  ItemName  Condition  MaxPrice MaxPriceInventoryID  
ITEM001 Lg Widget NEW        $3.99    INV123
ITEM001 Lg Widget USED       $1.99    INV234  

I'm trying this:

SELECT 
  ItemID, ItemName, b.condition, b.maxprice, 
    InventoryID as MaxPriceInventoryID
FROM
  Items I join inventory v On i.ItemID= v.ItemID
    join (
        select inventory.ItemID, max(Price) as MaxPrice, condition
            from inventory join Items on inventory.ItemID = Items.ItemID
            group by inventory.ItemID, condition) as b 
    on b.ItemID = v.ItemID and b.MaxPrice = v.Price
 ORDER BY
    ItemName, Condition

Unfortunately, this doesn't give the desired result: it seems to sporadically return max price for the item across all conditions, not max price for the item in a given condition

Ideas?

It's not entirely clear to me precisely how your data are related or how you need to filter.

I'd either do it this way:

SELECT ii.ItemID
    ,ii.ItemName
    ,ii.Condition
    ,ii.Price AS MaxPrice
    ,ii.MaxPriceInventoryID
FROM (
    SELECT i.ItemID
        ,i.ItemName
        ,i.ProductName
        ,v.InventoryID
        ,v.Condition
        ,v.Price
        ,DENSE_RANK() OVER (PARTITION BY v.ItemID, v.Condition ORDER BY v.Price DESC) AS R
    FROM Items i
    INNER JOIN Inventory v
        ON  i.ItemID = v.ItemID
    WHERE 1 = 1 /* Place your filtering conditionals here */
    ) AS ii
WHERE ii.R = 1
ORDER BY ii.ItemName
    ,ii.Condition

Or this way:

SELECT i.ItemID
    ,i.ItemName
    ,vv.Condition
    ,vv.Price AS MaxPrice
    ,vv.MaxPriceInventoryID
FROM Items i
INNER JOIN (
    SELECT v.ItemID
        ,v.InventoryID
        ,v.Condition
        ,v.Price
        ,DENSE_RANK() OVER (PARTITION BY v.ItemID, v.Condition ORDER BY v.Price DESC) AS R
    FROM  Inventory v
    WHERE 1 = 1 /* Place your filtering conditionals here */
    ) AS vv
    ON  i.ItemID = vv.ItemID
WHERE vv.R = 1
ORDER BY i.ItemName
    ,vv.Condition

If you only want one ItemID even when you have ties on price, then you can replace DENSE_RANK() with ROW_NUMBER() . However, unless you add a key field to your ORDER BY in the OVER() clause, the result will not be deterministic.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM