CREATE TABLE dbo.SalesRecords ( SalesPersonID int NOT NULL, SaleDate datetime, SaleCategory smallint, SaleAmount money ) INSERT INTO dbo.SalesRecords VALUES(100, '10/2/2012', 1, 200.00) INSERT INTO dbo.SalesRecords VALUES(100, '10/1/2012', 2, 200.00) INSERT INTO dbo.SalesRecords VALUES(100, '9/1/2012', 1, 300.00) INSERT INTO dbo.SalesRecords VALUES(100, '9/2/2012', 2, 400.00) INSERT INTO dbo.SalesRecords VALUES(100, '9/15/2012', 2, 100.00) INSERT INTO dbo.SalesRecords VALUES(100, '9/20/2012', 1, 250.00) INSERT INTO dbo.SalesRecords VALUES(200, '10/2/2012', 1, 200.00) INSERT INTO dbo.SalesRecords VALUES(200, '10/1/2012', 2, 200.00) INSERT INTO dbo.SalesRecords VALUES(200, '9/1/2012', 1, 300.00) INSERT INTO dbo.SalesRecords VALUES(200, '9/2/2012', 2, 400.00) INSERT INTO dbo.SalesRecords VALUES(200, '9/15/2012', 2, 100.00) INSERT INTO dbo.SalesRecords VALUES(200, '9/20/2012', 1, 250.00)You may be asked to return a list of the date and amount of first sale made in each month by each sales person. We could try to do that like this, by using the MIN function on the date, but this gives us the SaleAmount for each day, not the min for each month.
SELECT SalesPersonID, saleamount, MIN(saledate) FROM salesrecords WHERE saledate between '9/1/2012' and '9/30/2012' GROUP BY SalesPersonID, saleamount, saledate HAVING saledate = MIN(saledate)A more effective way to handle this is using ROW_NUMBER() as follows:
;WITH ROW_NUM as ( SELECT SalesPersonID, SaleDate, SaleCategory, SaleAmount, ROW_NUMBER() OVER (PARTITION BY SalesPersonID, datepart(MM,saledate) ORDER BY SaleDate ASC ) as 'Sequence' FROM SalesRecords )If we just select all from the common Table Expression ROW_NUM, the results look like this:
SELECT SalesPersonID, SaleAmount, SaleDate FROM ROW_NUM WHERE sequence = 1 ORDER BY SaleDate DESC
And it returns a list of the SaleAmount of the first sale of each month for each SalesPersonID as shown here:
If you were interested in the last sale of the month instead of the first you could simply change the ORDER BY hint from ASC to DESC in your ROW_NUMBER() function and you would get the opposite results, sequence number 1 would be the last sale instead of the first.
Part 2 coming later...other ranking functions in SQL Server
Part 2 is now up...NTILE() function usage
How can I make two column out of one. That is, Range_From and Range_To for the column SalesPersonID.
ReplyDeleteFor example if I'v 500 Sales Persons working on different days. Data are:
Working of Sale Persons
-----------------------
SalePersonID SaleDate
001 2012-01-01
002 2012-01-01
003 2012-01-01
004 2012-01-01
.
.
150 2012-01-01
151 2012-01-02
152 2012-01-02
.
.
160 2012-01-02
161 2012-01-03
164 2012-01-04
165 2012-01-04
.
.
500 2012-01-04
I want to have result like:
Working of Sale Persons
-----------------------
Range_From Range_To SaleDate
001 150 2012-01-01
151 160 2012-01-02
161 161 2012-01-03
162 500 2012-01-04
How do you define the ranges of ID's? I will need that to make this work.
Delete