Sql to find top3 for each record

Here is some sample data from a table named Customer Orders

CustomerID     CustomerOrderDate    OrderAmount
1                         10/11/2016                     300
1                         10/25/2016                     200
1                          9/01/2016                      700
1                         8/21/2016                       375
1                         5/31/2016                       6666
1                         02/01/2016                     433
2                         11/01/2016                     1000
2                         10/01/2016                     790

(Note: There are thousands of customers...to save space I just included 2 customers  

Trying to write a query that would list each customer id along with the last 3 orders along with sales amount for each of those orders

 (possible customers have less than 3 orders... would like the order dates to appear in the fields in reverse chronological order)



Using the above data I would like the query results to be

CustomerID  LastOrder1    SalesAmount1  LastOrder2    SalesAmount2        LastOrder3   SalesAmount3
1                     09/01/2016    700                     10/11/2016      300                         10/25/2016     200
2                     10/01/2016    790                    11/01/2016      1000
johnnyg123Asked:
Who is Participating?
 
PortletPaulConnect With a Mentor freelancerCommented:
oh! I'm sorry. to be honest I didn't even notice that portion of the question.

I will suggest using "conditional aggregates" for that part:
SELECT
        CustomerID
      , max(case when rn = 1 then CustomerOrderDate end) as LastOrder1
      , max(case when rn = 1 then OrderAmount end)       as SalesAmount1
      , max(case when rn = 2 then CustomerOrderDate end) as LastOrder2
      , max(case when rn = 2 then OrderAmount end)       as SalesAmount2
      , max(case when rn = 3 then CustomerOrderDate end) as LastOrder3
      , max(case when rn = 3 then OrderAmount end)       as SalesAmount3
FROM (SELECT
                CustomerID
              , CustomerOrderDate
              , OrderAmount
                row_number () OVER (PARTITION BY CustomerID
        ORDER BY CustomerOrderDate DESC) AS rn
        FROM [orders] o) d
WHERE rn <= 3
GROUP BY
        CustomerID

Open in new window

0
 
PortletPaulfreelancerCommented:
use ROW_NUMBER()
SELECT
        CustomerID
      , CustomerOrderDate
      , OrderAmount
      , ROW_NUMBER() OVER (PARTITION BY CustomerID 
                           ORDER BY CustomerOrderDate DESC) AS rn
FROM [orders] o
WHERE rn <= 3
ORDER BY
        CustomerID
      , rn

Open in new window

inside the OVER() the partition restarts counting at 1 for each customerid and the order by determines the way the numbers increment (most recent dates achieved via DESCending order)
0
 
johnnyg123Author Commented:
did not like rn in where clause

got error message indicating invalid column
0
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

 
Jeff DarlingDeveloper AnalystCommented:
Here is an old piece of code that I had from SQL server 2000.

I modified it to use your test data.  

-- Create a  table 
create Table #Table1 (
    CustomerID varchar(20)
    ,CustomerOrderDate datetime
    ,OrderAmount money
	);
	
create Table #Table2 (
    Rownumber INTEGER IDENTITY(1, 1)
    ,CustomerID varchar(20)
    ,CustomerOrderDate datetime
    ,OrderAmount money
	);	
	
	
-- add some records 
Insert into #Table1 (CustomerID,CustomerOrderDate,OrderAmount) values  ('1','10/11/2016',300)
Insert into #Table1 (CustomerID,CustomerOrderDate,OrderAmount) values  ('1','10/25/2016',200)
Insert into #Table1 (CustomerID,CustomerOrderDate,OrderAmount) values  ('1','9/01/2016',700)
Insert into #Table1 (CustomerID,CustomerOrderDate,OrderAmount) values  ('1','8/21/2016',375)
Insert into #Table1 (CustomerID,CustomerOrderDate,OrderAmount) values  ('1','5/31/2016',6666)
Insert into #Table1 (CustomerID,CustomerOrderDate,OrderAmount) values  ('1','2/01/2016',433)
Insert into #Table1 (CustomerID,CustomerOrderDate,OrderAmount) values  ('2','11/01/2016',1000)
Insert into #Table1 (CustomerID,CustomerOrderDate,OrderAmount) values  ('2','10/01/2016',790)

Insert into #Table2 (CustomerID,CustomerOrderDate,OrderAmount)
select CustomerID,CustomerOrderDate,OrderAmount from #Table1 order by CustomerID,OrderAmount desc

Select CustomerID,CustomerOrderDate,OrderAmount from 
(
SELECT    t.CustomerID, CustomerOrderDate,OrderAmount,t.Rownumber - o.Offset as SetRowNumber
FROM      #Table2 t
          INNER JOIN (
            SELECT    CustomerID, MIN(Rownumber) - 1 AS Offset
            FROM      #Table2
            GROUP BY  CustomerID
          ) o ON o.CustomerID = t.CustomerID    
) G1
Where SetRowNumber <4

drop table #Table1
drop table #Table2

Open in new window

0
 
PortletPaulfreelancerCommented:
My fault... sorry..
SELECT
        CustomerID
      , CustomerOrderDate
      , OrderAmount
FROM (SELECT
                CustomerID
              , CustomerOrderDate
              , OrderAmount
                row_number () OVER (PARTITION BY CustomerID
        ORDER BY CustomerOrderDate DESC) AS rn
        FROM [orders] o) d
WHERE rn <= 3
ORDER BY
        CustomerID
      , CustomerOrderDate DESC

Open in new window

0
 
johnnyg123Author Commented:
Actually did get it to work using the following

SELECT
        CustomerID
      , CustomerOrderDate
      , OrderAmount From

(

SELECT
        CustomerID
      , CustomerOrderDate
      , OrderAmount
      , ROW_NUMBER() OVER (PARTITION BY CustomerID
                           ORDER BY CustomerOrderDate DESC) AS rn
FROM [orders])  o
WHERE rn <= 3


However,

Not sure how to get in the format

  CustomerID  LastOrder1    SalesAmount1  LastOrder2    SalesAmount2        LastOrder3   SalesAmount3
 1                     09/01/2016    700                     10/11/2016      300                         10/25/2016     200
 2                     10/01/2016    790                    11/01/2016      1000
0
 
johnnyg123Author Commented:
Thanks!!!!!!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.