简体   繁体   中英

How do I exclude certain values from an average in SQL oracle

If I have this table: Item(ItemID, descr, onhand, price)

I am looking for prices that fall below the average of all the others. So let's say I have item 1 , then I would be comparing it to the average of items 2-5 rather than the average of items 1-5 . I know it will be a correlated subquery, but I can't figure out this bit about the average. So how do I exclude a non-specific item from the average?

EDIT : as proved by @1010's transforms we can just compare items price to total average.

Smart solution:

( provides same results as straightforward, but executes much faster on large data )

SELECT 
    t.ItemId,
    t.descr,
    t.onhand,
    t.price
from Item t
JOIN (
SELECT AVG(price) AS price
FROM Item 
) item_avg ON t.price < item_avg.price

Straightforward solution:

This does the trick, however, at the moment I can't see ways to optimize it (it's an "execution plan killer")

SELECT 
    t.ItemId,
    t.descr,
    t.onhand,
    t.price
from Item t
WHERE t.price < (
  SELECT AVG(T2.price) 
  FROM Item t2 
  WHERE t2.ItemId <> t.ItemID
)

For a table with such values:

ItemId  descr   onhand  price   CalculatedAverage
1       desc1   1       23      40
2       desc2   1       5       44.5
3       desc3   1       100     20.75
4       desc4   1       35      37
5       desc5   1       20      40.75

It produces the following output

ItemId  descr   onhand  price
1       desc1   1       23
2       desc2   1       5
4       desc4   1       35
5       desc5   1       20

let's say item i has price p_i, then you want to check

p_i < (p_1 + ... + p_i-1 + p_i+1 + ... + p_n)/(n-1)

but it's equivalent to

      p_i * (n-1) < (p_1 + ... + p_n) - p_i

p_i * (n-1) + p_i < (p_1 + ... + p_n)

  p_i * (n-1 + 1) < (p_1 + ... + p_n)

    (p_i * n) / n < (p_1 + ... + p_n) / n

              p_i < AVG(p)

so just compare each price with the average of all prices. it's the same.

EDIT

following Kirill's suggestion here's another query to get the prices below the average

SELECT ItemID, descr, onhand, price
  FROM Item
 WHERE price < (SELECT AVG(price) FROM Item)

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