Author |
Topic |
SergioM
Posting Yak Master
170 Posts |
Posted - 2012-07-25 : 10:42:18
|
I'm trying to brainstorm on how to write the following code, but I'm stumped. So, while I'm not asking you to write it, I wonder how it can be written. I have a list of sales. Amongst other data, each row has a SKU & a date. I need to find the last 10 sales for each SKU.So if my list looks like this:OrderID SKU Date25 CandyBar 5/12/201226 Chocolate 5/12/201227 CandyBar 5/13/201228 Gum 5/13/201229 CandyBar 5/13/201230 Chocolate 5/14/201231 CandyBar 5/14/201232 Gum 5/15/201233 Gum 5/15/2012 I have to make it look like this:SKU 10th 9th 8th 7thCandyBar 5/12/2012 5/13/2012 5/13/2012 5/14/2012Chocolate 5/12/2012 5/14/2012 Gum 5/13/2012 5/15/2012 5/15/2012 Any thoughts on where to start, or how (using words or SQL) you might write it? |
|
sunitabeck
Master Smack Fu Yak Hacker
5155 Posts |
Posted - 2012-07-25 : 10:54:27
|
You can use a combination of row_number function and pivoting to do this. Since you asked only for psuedo code, this is REALLY pseudo (a.k.a. completely untested ;);WITH cte1 AS( SELECT SKU,Date, ROW_NUMBER() OVER(PARTITION BY sku ORDER BY Date DESC) AS RN FROM YourTable)SELECT *FROM cte1PIVOT( MAX(date) FOR RN IN ([1],[2],[3],[4],[5])) P |
 |
|
SergioM
Posting Yak Master
170 Posts |
Posted - 2012-07-25 : 11:24:53
|
Nice! Thanks! It doesn't work, but it's 13 lines of code. I don't think it should take too long to figure this out. |
 |
|
Lamprey
Master Smack Fu Yak Hacker
4614 Posts |
Posted - 2012-07-25 : 11:49:45
|
Welcome to set-based programing. Sometimes it takes a fraction of the lines of code that a procedural language would. Sometimes it takes many times the LOC that a procedural language would.. :) |
 |
|
SergioM
Posting Yak Master
170 Posts |
Posted - 2012-07-25 : 14:29:37
|
Ok, I was wrong. It actually uses a few different commands I'm not familiar with. Little help? |
 |
|
sunitabeck
Master Smack Fu Yak Hacker
5155 Posts |
Posted - 2012-07-25 : 14:54:39
|
You can copy the code below to a SSMS window and run it. I added comments explaining what I am trying to do.-- CREATE A TEST TABLE WITH THE COLUMNS DESCRIBED IN YOUR ORIGINAL POSTCREATE TABLE #tmp (OrderID INT, SKU VARCHAR(64), Date DATETIME);-- INSERT THE SAMPLE DATA.insert into #tmp values ('25','CandyBar','5/12/2012');insert into #tmp values ('26','Chocolate','5/12/2012');insert into #tmp values ('27','CandyBar','5/13/2012');insert into #tmp values ('28','Gum','5/13/2012');insert into #tmp values ('29','CandyBar','5/13/2012');insert into #tmp values ('30','Chocolate','5/14/2012');insert into #tmp values ('31','CandyBar','5/14/2012');insert into #tmp values ('32','Gum','5/15/2012');insert into #tmp values ('33','Gum','5/15/2012');-- THE INNER QUERY WITHIN THE CTE ADDS A ROW NUMBER ORDERED-- THE WAY WE WANT THE PIVOT COLUMNS TO BE ORDERED. YOU WILL-- SEE THIS IF YOU RUN THIS QUERYSELECT SKU,Date, ROW_NUMBER() OVER(PARTITION BY sku ORDER BY Date DESC) AS RNFROM #tmp-- THE ACTUAL QUERY TAKES THE RESULTS OF THE CTE (THE INNER QUERY)-- AND PIVOTS IT.;WITH cte1 AS( SELECT SKU,Date, ROW_NUMBER() OVER(PARTITION BY sku ORDER BY Date DESC) AS RN FROM #tmp)SELECT *FROM cte1PIVOT( MAX(date) FOR RN IN ([1],[2],[3],[4],[5])) P-- CLEAN UPDROP TABLE #tmp; |
 |
|
SergioM
Posting Yak Master
170 Posts |
Posted - 2012-07-25 : 15:51:38
|
Wow, thanks again!I now realize that he error I was getting may be related to one server. I have two SQL 2008 servers. It works perfectly on one of them & on the other it gives me an error on line 39.PIVOT( MAX(date) FOR RN IN ([1],[2],[3],[4],[5])) P Msg 102, Level 15, State 1, Line 39Incorrect syntax near '('. I would have guessed that it is a database constraint, but this is all on a temp table. Both are SQL 2008. Do you know if there is a server-wide setting that I need to change?Thanks again, this was extremely helpful. |
 |
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2012-07-25 : 16:58:55
|
Yes, check the Compatibility setting on the database. N 56°04'39.26"E 12°55'05.63" |
 |
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2012-07-25 : 17:11:07
|
[code]DECLARE @Sample TABLE ( OrderID INT NOT NULL, SKU VARCHAR(64) NOT NULL, [Date] DATETIME );INSERT @Sample ( OrderID, SKU, [Date] )VALUES (25, 'CandyBar', '20120512'), (26, 'Chocolate', '20120512'), (27, 'CandyBar', '20120513'), (28, 'Gum', '20120513'), (29, 'CandyBar', '20120513'), (30, 'Chocolate', '20120514'), (31, 'CandyBar', '20120514'), (32, 'Gum', '20120515'), (33, 'Gum', '20120515');-- SolutionSELECT p.SKU, p.[1] AS [10th], p.[2] AS [9th], p.[3] AS [8th], p.[4] AS [7th], p.[5] AS [6th], p.[6] AS [5th], p.[7] AS [4th], p. AS [3rd], p.[9] AS [2nd], p.[10] AS [1st]FROM ( SELECT SKU, [Date], ROW_NUMBER() OVER (PARTITION BY SKU ORDER BY OrderID) AS rn FROM @Sample ) AS sPIVOT ( MAX(s.[Date]) FOR s.rn IN ([1], [2], [3], [4], [5], [6], [7], , [9], [10]) ) AS pORDER BY p.SKU[/code] N 56°04'39.26"E 12°55'05.63" |
 |
|
|
|
|