10

Below is my Table

Table1

+--------+----------+---------+  
| amount | make     | product |  
+--------+----------+---------+  
|    100 | Nokia    | Mobiles |   
|    300 | Samesung | Mobiles |   
|    700 | Micromax | Mobiles |   
|   1000 | Karbonn  | Mobiles |   
|    500 | Lava     | Mobiles |   
|    100 | Floyer   | Gift    |   
|    500 | Arichies | Gift    |   
|    300 | Feeling  | Gift    |   
+--------+----------+---------+  

Now I want to display the two highest amount for each product...

So I want to build single SQL query which gives me result as below..

+--------+----------+---------+  
| amount | make     | product |  
+--------+----------+---------+  
|   1000 | Karbonn  | Mobiles |   
|    700 | Micromax | Mobiles |   
|    500 | Arichies | Gift    |   
|    300 | Feeling  | Gift    |   
+--------+----------+---------+  

Kindly help me to build such query..

Lion
  • 18,729
  • 22
  • 80
  • 110
mahesh
  • 4,625
  • 11
  • 42
  • 61

5 Answers5

10

You can use this solution to retrieve the "group-wise maximum" based on the amount:

SELECT a.*
FROM Table1 a
INNER JOIN Table1 b ON a.product = b.product AND a.amount <= b.amount
GROUP BY a.amount, a.product
HAVING COUNT(*) <= 2

Simply change the 2 to however many of the top rows you want to retrieve per product.

If you wanted to retrieve the lowest two rows per product, you can simply change the <= sign in the INNER JOIN to a >=.

You can fiddle around with this solution here: SQL-Fiddle Demo

Zane Bien
  • 22,685
  • 6
  • 45
  • 57
4
select product, make, amount, rnk
from (
  select l.product, l.make, l.amount, count(*) as rnk
  from table1 as l
  left join table1 as r
  on (r.product = l.product and l.amount <= r.amount) 
  group by l.product, l.make
) a
where rnk <= 2

see the ideea and other examples here: http://www.xaprb.com/blog/2005/09/27/simulating-the-sql-row_number-function/

and sql fiddle based on zane bien test data.

Florin Ghita
  • 17,525
  • 6
  • 57
  • 76
1
SELECT a.*
FROM Table1 a
INNER JOIN Table1 b ON a.product = b.product AND a.amount <= b.amount
GROUP BY a.amount, a.product
HAVING COUNT(*) <= 2
ORDER BY a.amount desc

Please refer to http://sqlfiddle.com/#!2/9ba82/1

sel
  • 4,982
  • 1
  • 16
  • 22
0
select top 2 amount, make, product from table1 
where product='Mobiles'
order by amount desc
union
select top 2 amount, make, product from table1 
where product='Gift'
order by amount desc
Ricky
  • 363
  • 1
  • 8
0

You can do it in two ways: 1) Add Row Index column that will reflect the order and then select all rows with Row <= 2

SELECT amount, make,product
FROM 
(SELECT  ROW_NUMBER() OVER (PARTITION BY [product] ORDER BY [amount] DESC) AS [RowID],*
FROM [dbo].[Table1]) RESULT
WHERE RowID <= 2

2) You can also join the table to itself

SELECT a1.* FROM Table1 AS a1
  LEFT JOIN Table1 AS a2 
    ON a1.product = a2.product AND a1.amount<= a2.amount
GROUP BY a1.product
HAVING COUNT(*) <= 2;
Andrej K
  • 1,794
  • 1
  • 17
  • 37