Click here to Skip to main content
15,891,864 members
Please Sign up or sign in to vote.
4.20/5 (3 votes)
Hi Dear All,


Could any one please help meeeee............

I have a table in SQLSERVER as follows
SQL
id    PName       MinAmount  
1     aa           2.3
2     aa           3.5
3     bbb          6.5
4     bbb          5.2
5     bbb          4.2
6     bbb          7.2
7     bbb          5.6
8     bbb          4.3
9     bbb          8.7
10    cc           2.8
11    cc           3.1
12    cc           2.9
13    dd           5.1
14    ee           9.2
15    ee           8.5
16    ee           7.3

I would like to get a result from this table as add 2 extra columns for showing
cheapest PNames . chepest 2 PNames in column 1 and next 2 cheapest in next 2 column as shown below.
SQL
id    PName           VeryCheap      Moderate
1     aa                2.3            Null
                        3.5            Null  

2     bbb               4.2            5.2
                        4.3            5.6
 
3     cc                2.8            3.1
                        2.9            Null

4     dd                5.1            Null


5     ee                7.3            9.2
                        8.5            Null


Kindly tell me how to write the select query for this ?

Thank You Friends... hav a nice time...tc.. :)
Posted
Updated 25-Aug-14 3:01am
v2
Comments
Herman<T>.Instance 25-Aug-14 8:50am    
any example sql what shows what you have tried and where you are stuck?
SubhashRokzzz 25-Aug-14 9:00am    
Hi digimanus ,
I would like to get first two cheapest and next 2 cheapest records from the table
It is a product table..user wants to find out first 4 cheapest items from the table
SteveyJDay 25-Aug-14 9:04am    
I think he means try it yourself and post the SQL when you get stuck.
Magic Wonder 25-Aug-14 9:05am    
Why are you looking data in this format?
Vinay Mistry 25-Aug-14 9:30am    
I think not possible in single query. Use sub query.

1 solution

Well I found a way to get most of the way there using PIVOT and PARTITION and a temporary table but it's not elegant and it doesn't exactly match your expected outputs ...

Firstly, the id in your expected results seems meaningless as you want to combine multiple ids into a single set of results. I've ignored it.

Secondly, I don't know of any way of presenting the results as you have (partial data on the next row).

So here goes...

Firstly I ranked all of the data by PName and filtered out only rankings 1 through 4 (I've put an 'A' in front of the rank because I want to use that column as a column name later)
SQL
select
     PName,
     'A' + cast(rn as varchar) as colname,
  MinAmount

from
    (select PName, MinAmount,
    row_number() over (partition by PName order by MinAmount)  as rn
      from test) rankings
where rn IN (1,2,3,4)
This gave me the following results...
PNAME 	COLNAME MINAMOUNT
aa 	A1 	2.3 
aa 	A2 	3.5 
bbb 	A1 	4.2 
bbb 	A2 	4.3 
bbb 	A3 	5.2 
bbb 	A4 	5.6 
cc 	A1 	2.8 
cc 	A2 	2.9 
cc 	A3 	3.1 
dd 	A1 	5.1 
ee 	A1 	7.3 
ee 	A2 	8.5 
ee 	A3 	9.2 
I then used PIVOT on that data to get the rankings A1 to A4 as columns, putting the results into a temporary table. The whole query becomes
with filtered as
(
 select
     PName,
     'A' + cast(rn as varchar) as colname,
  MinAmount

from
    (select PName, MinAmount,
    row_number() over (partition by PName order by MinAmount)  as rn
      from test) rankings
where rn IN (1,2,3,4)
)
select * 
into #test1
FROM (
    SELECT 
        PName,
        colname,
        MinAmount
    FROM filtered
) as s
PIVOT
(
    SUM(MinAmount)
    FOR [colname] IN (A1,A2,A3,A4)
) as apivot
This gave the following results - which might actually be all you need depending on how you intend to display the results (in which case no need for the temporary table)
PNAME	A1	A2	A3	A4
aa 	2.3 	3.5 	(null) (null) 
bbb 	4.2 	4.3 	5.2 	5.6 
cc 	2.8 	2.9 	3.1 	(null) 
dd 	5.1 	(null) (null) 	(null) 
ee 	7.3 	8.5 	9.2 	(null) 

I finished off with the following query to get the results fairly close to the expected results you posted
SQL
SELECT PNAME, A1 as VeryCheap, A3 as Moderate FROM #test1
UNION ALL
SELECT PNAME, A2, A4 FROM #test1 where A2 is not null
ORDER BY 1,2
Note the check for not null on the second query to filter out some of the "rubbish"
 
Share this answer
 
Comments
Jörgen Andersson 25-Aug-14 16:34pm    
What do you mean 'not elegant'? :-)
Considering the request this is very good.
Pity it's not SQLServer 2012, then you could have used Lag() and case to remove the duplicated pname from the second row.
CHill60 26-Aug-14 9:53am    
I almost posted a 2012 solution! Glad I spotted the version in time. Cheers! :-)
SubhashRokzzz 27-Aug-14 7:31am    
Thank You Very much CHill60.. your solution helped me a lot... :D

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900