Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
WillieMakit
Starting Member
1 Post |
Posted - 2010-01-09 : 15:06:37
|
| I have inherited a piece of code that is a bit of a pig. It uses a cursor to loop through a list of stores and count customers. I would like to change this to use a CTE, but am not sure how to configure it. The basic functionality of the SP is:Declare variablesSet up start and end dates Declare CursorGet a list of stores to checkOpen the CursorWhile… Loops through the stores Insert a new record into the Destination Table Count up the new customers for this store Count up the returning customers to the store Update the new record with the totalsLoop The code:view plaincopy to clipboardprint?01.DECLARE @StartDate datetime 02.DECLARE @EndDate datetime 03.DECLARE @Location varchar 04.DECLARE @Count int 05.DECLARE @Duration int 06. 07.SET @StartDate = (SELECT TOP 1 TheDate from Customers 08.ORDER BY TheDate DESC) 09. 10.IF @StartDate IS NULL 11.BEGIN 12. SET @StartDate = DATEADD(dd, 1, '12/31/2008') 13.END 14.ELSE 15.BEGIN 16. SET @StartDate = DATEADD(dd, 1, @StartDate) 17.END 18.SET @EndDate = DATEADD(dd, 1, @StartDate) 19. 20.-- If StartDate = Today, we don't want to do the update 21. 22.DECLARE VSCursor CURSOR FOR 23. SELECT AcctNo, Location 24. FROM Stores 25. WHERE Status < 3 26. 27.DECLARE @AcctNo INT 28.SELECT @AcctNo = 0 29.SELECT @Count = 0 30. 31.OPEN VSCursor 32.WHILE (0=0) BEGIN 33. FETCH NEXT FROM VSCursor INTO @AcctNo, @Location 34. 35. IF @@FETCH_STATUS <> 0 BREAK 36. 37. INSERT INTO Customers(TheDate, AcctNo) VALUES(@StartDate, @AcctNo ) 38. 39. -- Now select all totals for New Customers 40. SET @Count = ( 41. SELECT TOP 1 COUNT(DISTINCT NextTrip.Store) 42. FROM FirstTrip 43. LEFT OUTER JOIN NextTrip ON FirstTrip.CustID = NextTrip.CustID 44. WHERE (NextTrip.DTEnter >= @StartDate) AND (NextTrip.DTEnter < @EndDate) AND NextTrip.isBot = 0 AND (NextTrip.isRet = 0) AND (FirstTrip.AcctNo = @AcctNo) AND NextTrip.Store <> @Location 45. GROUP BY CONVERT(DATETIME, FLOOR(CONVERT(NUMERIC(18,9),NextTrip.DTEnter))), FirstTrip.AcctNo) 46. 47. SET @Duration = ( 48. SELECT TOP 1 SUM(NextTrip.Dur) AS Duration 49. FROM FirstTrip 50. LEFT OUTER JOIN NextTrip ON FirstTrip.CustID = NextTrip.CustID 51. WHERE (NextTrip.DTEnter >= @StartDate) AND (NextTrip.DTEnter < @EndDate) AND NextTrip.isBot = 0 AND (NextTrip.isRet = 0) AND (FirstTrip.AcctNo = @AcctNo) AND NextTrip.Store <> @Location 52. GROUP BY CONVERT(DATETIME, FLOOR(CONVERT(NUMERIC(18,9),NextTrip.DTEnter))), FirstTrip.AcctNo) 53. 54. UPDATE Customers SET NewCust = @Count, NewCustDur = @Duration WHERE TheDate = @StartDate and AcctNo = @AcctNo 55. 56. -- Now get all the totals for Returning Customers 57. SET @Count = 58. ( 59. SELECT TOP 1 COUNT(DISTINCT NextTrip.Store) 60. FROM FirstTrip 61. LEFT OUTER JOIN NextTrip ON FirstTrip.CustID = NextTrip.CustID 62. WHERE NextTrip.isBot = 0 AND NextTrip.Store <> @Location AND NextTrip.CustID IN 63. ( 64. SELECT DISTINCT FirstTrip.CustID from FirstTrip 65. INNER JOIN NextTrip ON NextTrip.CustID = FirstTrip.CustID 66. WHERE FirstTrip.AcctNo = @AcctNo and FirstTrip.DateOn >= @StartDate and FirstTrip.DateOn < @EndDate and NextTrip.IsRet = 1 67. ) 68. GROUP BY CONVERT(DATETIME, FLOOR(CONVERT(NUMERIC(18,9),NextTrip.DTEnter))), FirstTrip.AcctNo 69. ) 70. 71. SET @Duration = 72. ( 73. SELECT TOP 1 SUM(NextTrip.Dur) AS Duration 74. FROM FirstTrip 75. LEFT OUTER JOIN NextTrip ON FirstTrip.CustID = NextTrip.CustID 76. WHERE NextTrip.isBot = 0 AND NextTrip.Store <> @Location AND NextTrip.CustID IN 77. ( 78. SELECT DISTINCT FirstTrip.CustID from FirstTrip 79. INNER JOIN NextTrip ON NextTrip.CustID = FirstTrip.CustID 80. WHERE FirstTrip.AcctNo = @AcctNo and FirstTrip.DateOn >= @StartDate and FirstTrip.DateOn < @EndDate and NextTrip.IsRet = 1 81. ) 82. GROUP BY CONVERT(DATETIME, FLOOR(CONVERT(NUMERIC(18,9),NextTrip.DTEnter))), FirstTrip.AcctNo 83. ) 84. 85. UPDATE Customers SET RetCust = @Count, RetCustDur = @Duration WHERE TheDate = @StartDate and AcctNo = @AcctNo 86. 87.END 88.CLOSE VSCursor 89.DEALLOCATE VSCursor DECLARE @StartDate datetimeDECLARE @EndDate datetimeDECLARE @Location varcharDECLARE @Count intDECLARE @Duration intSET @StartDate = (SELECT TOP 1 TheDate from CustomersORDER BY TheDate DESC)IF @StartDate IS NULLBEGIN SET @StartDate = DATEADD(dd, 1, '12/31/2008')ENDELSEBEGIN SET @StartDate = DATEADD(dd, 1, @StartDate)ENDSET @EndDate = DATEADD(dd, 1, @StartDate)-- If StartDate = Today, we don't want to do the updateDECLARE VSCursor CURSOR FOR SELECT AcctNo, Location FROM Stores WHERE Status < 3DECLARE @AcctNo INTSELECT @AcctNo = 0SELECT @Count = 0OPEN VSCursorWHILE (0=0) BEGIN FETCH NEXT FROM VSCursor INTO @AcctNo, @Location IF @@FETCH_STATUS <> 0 BREAK INSERT INTO Customers(TheDate, AcctNo) VALUES(@StartDate, @AcctNo ) -- Now select all totals for New Customers SET @Count = ( SELECT TOP 1 COUNT(DISTINCT NextTrip.Store) FROM FirstTrip LEFT OUTER JOIN NextTrip ON FirstTrip.CustID = NextTrip.CustID WHERE (NextTrip.DTEnter >= @StartDate) AND (NextTrip.DTEnter < @EndDate) AND NextTrip.isBot = 0 AND (NextTrip.isRet = 0) AND (FirstTrip.AcctNo = @AcctNo) AND NextTrip.Store <> @Location GROUP BY CONVERT(DATETIME, FLOOR(CONVERT(NUMERIC(18,9),NextTrip.DTEnter))), FirstTrip.AcctNo) SET @Duration = ( SELECT TOP 1 SUM(NextTrip.Dur) AS Duration FROM FirstTrip LEFT OUTER JOIN NextTrip ON FirstTrip.CustID = NextTrip.CustID WHERE (NextTrip.DTEnter >= @StartDate) AND (NextTrip.DTEnter < @EndDate) AND NextTrip.isBot = 0 AND (NextTrip.isRet = 0) AND (FirstTrip.AcctNo = @AcctNo) AND NextTrip.Store <> @Location GROUP BY CONVERT(DATETIME, FLOOR(CONVERT(NUMERIC(18,9),NextTrip.DTEnter))), FirstTrip.AcctNo) UPDATE Customers SET NewCust = @Count, NewCustDur = @Duration WHERE TheDate = @StartDate and AcctNo = @AcctNo -- Now get all the totals for Returning Customers SET @Count = ( SELECT TOP 1 COUNT(DISTINCT NextTrip.Store) FROM FirstTrip LEFT OUTER JOIN NextTrip ON FirstTrip.CustID = NextTrip.CustID WHERE NextTrip.isBot = 0 AND NextTrip.Store <> @Location AND NextTrip.CustID IN ( SELECT DISTINCT FirstTrip.CustID from FirstTrip INNER JOIN NextTrip ON NextTrip.CustID = FirstTrip.CustID WHERE FirstTrip.AcctNo = @AcctNo and FirstTrip.DateOn >= @StartDate and FirstTrip.DateOn < @EndDate and NextTrip.IsRet = 1 ) GROUP BY CONVERT(DATETIME, FLOOR(CONVERT(NUMERIC(18,9),NextTrip.DTEnter))), FirstTrip.AcctNo ) SET @Duration = ( SELECT TOP 1 SUM(NextTrip.Dur) AS Duration FROM FirstTrip LEFT OUTER JOIN NextTrip ON FirstTrip.CustID = NextTrip.CustID WHERE NextTrip.isBot = 0 AND NextTrip.Store <> @Location AND NextTrip.CustID IN ( SELECT DISTINCT FirstTrip.CustID from FirstTrip INNER JOIN NextTrip ON NextTrip.CustID = FirstTrip.CustID WHERE FirstTrip.AcctNo = @AcctNo and FirstTrip.DateOn >= @StartDate and FirstTrip.DateOn < @EndDate and NextTrip.IsRet = 1 ) GROUP BY CONVERT(DATETIME, FLOOR(CONVERT(NUMERIC(18,9),NextTrip.DTEnter))), FirstTrip.AcctNo ) UPDATE Customers SET RetCust = @Count, RetCustDur = @Duration WHERE TheDate = @StartDate and AcctNo = @AcctNoENDCLOSE VSCursorDEALLOCATE VSCursorAny help in converting this to a cte would be much appreciated. Psuedo code would probably do fine.Thanks. |
|
|
visakh16
Very Important crosS Applying yaK Herder
52326 Posts |
Posted - 2010-01-10 : 01:16:24
|
you dont require a cte here. you just need this:-DECLARE @StartDate datetime DECLARE @EndDate datetime DECLARE @Location varchar DECLARE @Count int DECLARE @Duration int SET @StartDate = (SELECT TOP 1 TheDate from Customers ORDER BY TheDate DESC) IF @StartDate IS NULL BEGIN SET @StartDate = DATEADD(dd, 1, '12/31/2008') END ELSE BEGIN SET @StartDate = DATEADD(dd, 1, @StartDate) END SET @EndDate = DATEADD(dd, 1, @StartDate) INSERT INTO Customers(TheDate, AcctNo,NewCust,NewCustDur,RetCust,RetCustDur) SELECT @StartDate,s.AcctNo,t1.NewCustCnt,t1.NewCustDur,t2.RetCustCnt,t2.RetCustDurFROM Stores sOUTER APPLY ( SELECT TOP 1 COUNT(DISTINCT NextTrip.Store) AS NewCustCnt,SUM(NextTrip.Dur) AS NewCustDur FROM FirstTrip LEFT OUTER JOIN NextTrip ON FirstTrip.CustID = NextTrip.CustID WHERE (NextTrip.DTEnter >= @StartDate) AND (NextTrip.DTEnter < @EndDate) AND NextTrip.isBot = 0 AND (NextTrip.isRet = 0) AND (FirstTrip.AcctNo = s.AcctNo) AND NextTrip.Store <> s.Location GROUP BY CONVERT(DATETIME, FLOOR(CONVERT(NUMERIC(18,9),NextTrip.DTEnter))), FirstTrip.AcctNo)t1OUTER APPLY ( SELECT TOP 1 COUNT(DISTINCT NextTrip.Store) AS RetCustCnt,SUM(NextTrip.Dur) AS RetCustDurFROM FirstTrip LEFT OUTER JOIN NextTrip ON FirstTrip.CustID = NextTrip.CustID WHERE NextTrip.isBot = 0 AND NextTrip.Store <> s.Location AND NextTrip.CustID IN ( SELECT DISTINCT FirstTrip.CustID from FirstTrip INNER JOIN NextTrip ON NextTrip.CustID = FirstTrip.CustID WHERE FirstTrip.AcctNo = s.AcctNo and FirstTrip.DateOn >= @StartDate and FirstTrip.DateOn < @EndDate and NextTrip.IsRet = 1 ) GROUP BY CONVERT(DATETIME, FLOOR(CONVERT(NUMERIC(18,9),NextTrip.DTEnter))), FirstTrip.AcctNo )t2 WHERE Status < 3 |
 |
|
|
|
|
|
|
|