Solved

Sql to find top3 for each record

Posted on 2016-11-10
7
24 Views
Last Modified: 2016-11-10
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
0
Comment
Question by:johnnyg123
  • 3
  • 3
7 Comments
 
LVL 48

Expert Comment

by:PortletPaul
ID: 41882914
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
 

Author Comment

by:johnnyg123
ID: 41882943
did not like rn in where clause

got error message indicating invalid column
0
 
LVL 12

Expert Comment

by:Jeff Darling
ID: 41882948
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
What is SQL Server and how does it work?

The purpose of this paper is to provide you background on SQL Server. It’s your self-study guide for learning fundamentals. It includes both the history of SQL and its technical basics. Concepts and definitions will form the solid foundation of your future DBA expertise.

 
LVL 48

Expert Comment

by:PortletPaul
ID: 41882951
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
 

Author Comment

by:johnnyg123
ID: 41882966
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
 
LVL 48

Accepted Solution

by:
PortletPaul earned 500 total points
ID: 41882984
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
 

Author Closing Comment

by:johnnyg123
ID: 41883022
Thanks!!!!!!
0

Featured Post

VMware Disaster Recovery and Data Protection

In this expert guide, you’ll learn about the components of a Modern Data Center. You will use cases for the value-added capabilities of Veeam®, including combining backup and replication for VMware disaster recovery and using replication for data center migration.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Scheduling Jobs for Execution: 4 22
Updating ms sql with special characters 8 39
Stored Procedure 2 47
MS SQL Inner Join - Multiple Join Parameters 2 18
Audit has been really one of the more interesting, most useful, yet difficult to maintain topics in the history of SQL Server. In earlier versions of SQL people had very few options for auditing in SQL Server. It typically meant using SQL Trace …
Ever needed a SQL 2008 Database replicated/mirrored/log shipped on another server but you can't take the downtime inflicted by initial snapshot or disconnect while T-logs are restored or mirror applied? You can use SQL Server Initialize from Backup…
This demo shows you how to set up the containerized NetScaler CPX with NetScaler Management and Analytics System in a non-routable Mesos/Marathon environment for use with Micro-Services applications.
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

914 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now