create multiple rows based on data

Please support our MS SQL advertiser: Intel Parallel Studio Home
Reply

Join Date: Nov 2009
Posts: 5
Reputation: mattlightbourn is an unknown quantity at this point 
Solved Threads: 0
mattlightbourn mattlightbourn is offline Offline
Newbie Poster

create multiple rows based on data

 
0
  #1
24 Days Ago
Dear all,

I’m stuck on a problem which I’m hoping someone might be able to help with in an SQL script.

I have a table with RAW Timesheet data which includes entries for Absences. When someone enters a timesheet on a particular date for a two week holiday, if I report on the amount of hours recorded in the first week, it brings into account the next week’s absences as well.
My solution is that, when the data is imported from the Timesheet system into the SQL database, I want it to identify Absence records greater than one day and then create multiple records for each day taken. This way, I will always get accurate reports regardless of the date range of a report.
I am not great at scripting and am a little out of my depth but thought I would include where I have got up to (stuck though it be) to see if someone can see how to do this better or correct my mistakes.

The Timesheet record comes from a Timesheet table which is imported from a TXT file. The TimeDate field is the date the timesheet is entered OR the date for the first day’s holiday. The AbsenceDays field is how many days.

What I want to do is create a new record for every single day BUT, as it is creating each record, check the date against a Calendar table which checks to see if the proposed new record date is a WorkDay or not. The calendar has a [Date] field and a WorkDay Y/N field which is set to No if it is a weekend or is a Public Holiday.

Each Record it creates INTO a new table called Absences (which I haven’t included – but know needs to go after the print DATEADD but don’t know what to add) and the TimeDate is modified to the date created from the @counter increment and each AbsenceDays is set to 1 with exception to any remainder on the last record (like in the example of 3.5 days – records for 1, 1, 1, 0.5 would be created).

Sorry if this all looks convoluted but I wanted to ensure I explained myself fully before posting. Thank you all in advance.

Kind Regards

Matt


  1.  
  2. -- ****** Modified Version ******
  3.  
  4. declare @StartDate datetime
  5. declare @Days int
  6. declare @counter int
  7.  
  8. SET @StartDate = dbo.Timesheets.TimeDate
  9.  
  10. IF dbo.timesheets.AbsenceDays = <1 THEN
  11. end
  12. else
  13.  
  14. SET @counter = 0
  15.  
  16. -- The reason why counter is set to 0 and not 1 is because I want to create the initial record with the Timesheet date+0. This is because I do not want to keep the original record that is being used to duplicate and create each day timesheet.
  17.  
  18. while(@counter <= dbo.timesheets.AbsenceDays)
  19. begin
  20.  
  21. -- Somehow need to specify a relationship between dbo.Calendar.[Date] and dbo.timesheets.DateTime+@counter
  22.  
  23. CASE WHEN(dbo.Calendar.WorkDay = “Y” THEN continue ELSE @counter = @counter+1 redo case END)
  24.  
  25. -- Above case done to ensure that the date it is about to add is not a Sunday or Saturday or public holiday. Don’t know how to format it correctly.
  26.  
  27. print DATEADD(day, @counter, @StartDate)
  28.  
  29. -- I know I can insert record here but don’t know how. I want the same details as the original record being checked by the script but the TimeDate field to be changed to the new date and the AbsenceDays field to be set to 1 per records. In addition, if the absences are 3.5 days, I would need FOUR records created – 1, 1, 1, 0.5. When adding these records, how would I get it to create records which are not simply divided by 4? (namely 0.87 days per record)[/green]
  30.  
  31. SET @counter = @counter + 1
  32. end
Reply With Quote Quick reply to this message  
Join Date: Nov 2009
Posts: 5
Reputation: mattlightbourn is an unknown quantity at this point 
Solved Threads: 0
mattlightbourn mattlightbourn is offline Offline
Newbie Poster

A bit more info

 
0
  #2
24 Days Ago
I've done a little more work on this and explained a few things better. I also have provided the QUERY statement where it receives it data from.

Hope someone can help with this or point me in the right direction - it's the commands I don't know, must be a way.

Kind regards Matt

  1. -- This is the source Record Set. This is saved as a view: AbsenceFinder
  2.  
  3. SELECT TimeDate,
  4. YearNum,
  5. MonthNum,
  6. ResourceName,
  7. Studio_Company,
  8. ChargeDesc,
  9. AbHrs,
  10. CASE
  11. WHEN ROUND((abhrs / (Hours_pw/Days_pw)),0) < 0
  12. THEN
  13. 0 - ROUND((abhrs / (Hours_pw/Days_pw)),0)
  14. WHEN ROUND((abhrs / (Hours_pw/Days_pw)),0) > 1
  15. THEN
  16. ROUND((abhrs / (Hours_pw/Days_pw)),0)
  17. ELSE 1
  18. END
  19. AS NumRecords
  20. FROM dbo.FM_Timesheets
  21. WHERE ChargeCategory = 'Holidays/Absences'
  22.  
  23. -- ************* This is the script so far ****************
  24.  
  25. DECLARE @StartDate datetime
  26. DECLARE @Days int
  27. DECLARE @counter int
  28. SET @StartDate = dbo.FM_Timesheets.TimeDate
  29.  
  30. -- be careful of US dates (pass as parameters to SP)
  31.  
  32. SET @counter = 0
  33. SET @Days = dbo.FM_Timesheets.NumRecords
  34. WHILE (@counter <= @Days)
  35. BEGIN
  36. PRINT DATEADD(day, @counter, @StartDate) – don’t know what this does?
  37.  
  38. -- I’m guessing here, really don’t know how to create rows from script
  39.  
  40. IF SELECT dbo.Calendar.workdays = ‘Y’ FROM dbo.Calendar LEFT OUTER JOIN DATEADD(day, @counter, @StartDate) = dbo.Calendar.caldate THEN
  41.  
  42. UPDATE AbsenceFinder.TimeDate = DATEADD(day, @counter, @StartDate)
  43. UPDATE AbsenceFinder.YearNum = YEAR(DATEADD(day, @counter, @StartDate))
  44. UPDATE AbsenceFinder.MonthNum = MONTH(DATEADD(day, @counter, @StartDate))
  45. UPDATE AbsenceFinder.ResourceName = ResourceName
  46. UPDATE AbsenceFinder.StudioCompany = StudioCompany
  47. UPDATE AbsenceFinder.ChargeDesc = ChargeDesc
  48. UPDATE AbsenceFinder.AbHrs = (Hours_pw / Days_pw)
  49.  
  50. I need TO find a way of getting it TO look at remaining amount AND, IF less than a day, enter the remaining amount. Example, someone puts 0.5 days, that IS 3.75 hours. Full day 7.5.
  51. IF the sum of this persons timesheets (have TO put an ID ON there AS well TO ensure they are groupable together) < original 4.5 days (33.75 hours) AND remaining amount IS < (Hours_pw / Days_pw) then, value = remaining amount ELSE (Hours_pw / Days_pw).
  52.  
  53. INTO Absences
  54. FROM AbsenceFinder
  55. SET @counter = @counter + 1
  56. ELSE
  57. SET @counter = @counter + 1
  58. END
  59. END
  60.  
  61. Examples
  62. Original
  63. TimeDate YearNum MonthNum ResourceName StudioCompany ChargeDesc AbHrs
  64. 30/01/09 2009 01 Joe Bloggs Bristol Absence 33.75 (4.5 days)
  65.  
  66. After work done
  67. TimeDate YearNum MonthNum ResourceName StudioCompany ChargeDesc AbHrs
  68. 30/01/09 2009 01 Joe Bloggs Bristol Absence 7.5
  69. 31/01/09 2009 01 Joe Bloggs Bristol Absence 7.5
  70. 02/02/09 2009 02 Joe Bloggs Bristol Absence 7.5
  71. 03/02/09 2009 02 Joe Bloggs Bristol Absence 7.5
  72. 04/02/09 2009 02 Joe Bloggs Bristol Absence 3.75
Reply With Quote Quick reply to this message  
Join Date: Nov 2009
Posts: 5
Reputation: mattlightbourn is an unknown quantity at this point 
Solved Threads: 0
mattlightbourn mattlightbourn is offline Offline
Newbie Poster
 
0
  #3
24 Days Ago
Is there a way that I could modify this for my use? Instead of delimited, I want to do it WHERE NumRecords > 1. I still need it to verify the date that it increments to from a join to the dbo.calendar.caldate looking to ensure dbo.calendar.workdays = 'Y' before proceeding.

Thanks for your help with this

Matt

  1. (http://www.projectdmx.com/tsql/tblnumbers.aspx).
  2.  
  3. SELECT customerid,
  4. firstname,
  5. lastname,
  6. SUBSTRING(phone_numbers, n, CHARINDEX(' ', phone_numbers + ' ',
  7. n) - n) AS phone,
  8. n + 1 - LEN(REPLACE(LEFT(phone_numbers, n), ' ', '' )) AS
  9. phone_idx
  10. FROM Phones AS P
  11. CROSS JOIN (SELECT number
  12. FROM master..spt_values
  13. WHERE type = 'P'
  14. AND number BETWEEN 1 AND 100) AS Numbers(n)
  15. WHERE SUBSTRING(' ' + phone_numbers, n, 1) = ' '
  16. AND n < LEN(phone_numbers) + 1
  17. ORDER BY customerid, phone_idx
Reply With Quote Quick reply to this message  
Join Date: Nov 2009
Posts: 5
Reputation: mattlightbourn is an unknown quantity at this point 
Solved Threads: 0
mattlightbourn mattlightbourn is offline Offline
Newbie Poster
 
0
  #4
24 Days Ago
Is this looking any better? Really need help with this. Thanks

  1. IF dbo.Absenceview.NumRecords > 1
  2. THEN
  3. SET @AbsenceHours = dbo.Absenceview.Hours_pw /
  4. dbo.Absenseview.Days_pw)
  5. SET @RecCounter = dbo.Absenceview.NumRecords
  6. SET @AdjustDay = 0
  7. SET @DateCheck = 'N'
  8.  
  9. IF dbo.Absencerview.AbHrs / @ AbsenceHours = RecCounter
  10. SET @LastRec = @AbsenceHours
  11. ELSE
  12. SET @LastRec = (@RecCounter-(dbo.Absenceview.AbHrs /
  13. @AbsenceHours)) * @AbsenceHours
  14. END IF
  15.  
  16. SET @Looper = 1
  17. SET @AbDate = dbo.Absenceview.TimeDate
  18.  
  19. WHILE @Looper <= (@RecCounter-1)
  20.  
  21. INSERT INTO Absences
  22. (
  23. TimeDate,
  24. MonthNum,
  25. RecourceName,
  26. Studio_Company,
  27. ChargeDesc,
  28. AbHrs
  29. )
  30. VALUES
  31. (
  32. @AbDate,
  33. MONTH(@AbDate),
  34. dbo.Absenceview.ResourceName,
  35. dbo.Absenceview.Studio_Company,
  36. dbo.Absenceview.ChargeDesc,
  37. @AbsenceHours
  38. );
  39.  
  40. -- Check the next date to see if it is a valid WorkDay by looking up proposed date in dbo.Calendar
  41.  
  42. WHILE @DateCheck = 'N'
  43.  
  44. SET @adDate = DATEADD(day, (@Looper+@AdjustDay),
  45. @adDate)
  46.  
  47. SET @DateCheck = (SELECT dbo.Calendar.WorkDay FROM
  48. dbo.Calendar WHERE
  49. dbo.Calendar.CalDate = @adDate)
  50.  
  51. SET @AdjustDay = @AdjustDay + 1
  52.  
  53. END WHILE
  54.  
  55. -- ********************************************************************************
  56.  
  57. END WHILE
  58.  
  59. INSERT INTO Absences
  60. (
  61. TimeDate,
  62. MonthNum,
  63. RecourceName,
  64. Studio_Company,
  65. ChargeDesc,
  66. AbHrs
  67. )
  68. VALUES
  69. (
  70. @AbDate,
  71. MONTH(@AbDate),
  72. dbo.Absenceview.ResourceName,
  73. dbo.Absenceview.Studio_Company,
  74. dbo.Absenceview.ChargeDesc,
  75. @LastRec
  76. );
  77. ELSE
  78. INSERT INTO Absences
  79. (
  80. TimeDate,
  81. MonthNum,
  82. RecourceName,
  83. Studio_Company,
  84. ChargeDesc,
  85. AbHrs
  86. )
  87. VALUES
  88. (
  89. dbo.Absenceview.TimeDate,
  90. dbo.Absenceview.MonthNum,
  91. dbo.Absenceview.ResourceName,
  92. dbo.Absenceview.Studio_Company,
  93. dbo.Absenceview.ChargeDesc,
  94. dbo.Absenceview.AbHrs
  95. );
  96. END IF;
Reply With Quote Quick reply to this message  
Join Date: Nov 2009
Posts: 5
Reputation: mattlightbourn is an unknown quantity at this point 
Solved Threads: 0
mattlightbourn mattlightbourn is offline Offline
Newbie Poster
 
0
  #5
23 Days Ago
Ok, looks like I've done it using a cursor routine but, omg, crazy slow!!! Any ideas of improvements on this?

  1. IF EXISTS (SELECT 1
  2. FROM INFORMATION_SCHEMA.TABLES
  3. WHERE TABLE_TYPE='BASE TABLE'
  4. AND TABLE_NAME='Absences')
  5. DROP TABLE Absences
  6. ELSE
  7.  
  8. CREATE TABLE Absences(
  9. TimeDate DateTime,
  10. MonthNum varchar(2),
  11. YearNum varchar(25),
  12. ResourceName varchar(max),
  13. Studio_Company varchar(max),
  14. ChargeDesc varchar(max),
  15. AbHrs varchar(max),
  16. );
  17.  
  18. -- Populate with data
  19.  
  20. DECLARE @AbDate Datetime
  21. DECLARE @AbsenceHours Float
  22. DECLARE @LastRec Float
  23. DECLARE @RecCounter Int
  24. DECLARE @Looper Int
  25. DECLARE @AdjustDay Int
  26. DECLARE @DateCheck varchar(2)
  27.  
  28. DECLARE @curTimeDate DateTime
  29. DECLARE @curResourceName varchar(max)
  30. DECLARE @curChargeDesc varchar(max)
  31. DECLARE @curAbsenceHours real
  32.  
  33. /*Create cursor to look at every record in Absenceview */
  34. DECLARE @absence_cursor CURSOR
  35.  
  36. SET @absence_cursor = CURSOR FOR
  37. SELECT TimeDate,ResourceName,ChargeDesc,AbHrs FROM dbo.Absenceview
  38.  
  39. OPEN @absence_cursor
  40.  
  41. FETCH NEXT FROM @absence_cursor
  42. INTO @curTimeDate,@curResourceName,@curChargeDesc,@curAbsenceHours
  43.  
  44. WHILE @@FETCH_STATUS = 0
  45. BEGIN
  46. IF ((SELECT NumRecords
  47. FROM dbo.Absenceview
  48. WHERE TimeDate = @curTimeDate AND
  49. ResourceName = @curResourceName AND
  50. ChargeDesc = @curChargeDesc AND
  51. AbHrs = @curAbsenceHours) > 1)
  52. BEGIN
  53. SET @AbsenceHours =(( SELECT Hours_pw
  54. FROM dbo.Absenceview
  55. WHERE TimeDate = @curTimeDate AND
  56. ResourceName = @curResourceName AND
  57. ChargeDesc = @curChargeDesc AND
  58. AbHrs = @curAbsenceHours)
  59. /
  60. ( SELECT Days_pw
  61. FROM dbo.Absenceview
  62. WHERE TimeDate = @curTimeDate AND
  63. ResourceName = @curResourceName AND
  64. ChargeDesc = @curChargeDesc AND
  65. AbHrs = @curAbsenceHours))
  66.  
  67. SET @RecCounter = ( SELECT NumRecords FROM dbo.Absenceview
  68. WHERE TimeDate = @curTimeDate AND
  69. ResourceName = @curResourceName AND
  70. ChargeDesc = @curChargeDesc AND
  71. AbHrs = @curAbsenceHours)
  72. SET @AdjustDay = 0
  73. SET @DateCheck = 'N'
  74. --
  75. -- This is to check if the hours of LAST timesheet is <= full day hours.
  76. -- @LastRec will either be the same as @AbsenceHours or less.
  77. --
  78. IF ((SELECT AbHrs FROM dbo.Absenceview WHERE TimeDate = @curTimeDate AND
  79. ResourceName = @curResourceName AND
  80. ChargeDesc = @curChargeDesc AND
  81. AbHrs = @curAbsenceHours ) / @AbsenceHours = @RecCounter)
  82. BEGIN
  83. SET @LastRec = @AbsenceHours
  84. END
  85. ELSE
  86. BEGIN
  87. SET @LastRec = (@RecCounter-( SELECT AbHrs
  88. FROM dbo.Absenceview
  89. WHERE TimeDate = @curTimeDate AND
  90. ResourceName = @curResourceName AND
  91. ChargeDesc = @curChargeDesc AND
  92. AbHrs = @curAbsenceHours)/ @AbsenceHours) * @AbsenceHours
  93. END
  94. --
  95. -- Set the first Date. This will be the date the timesheet was entered
  96. --
  97. SET @Looper = 0
  98. SET @AbDate = ( SELECT TimeDate
  99. FROM dbo.Absenceview
  100. WHERE TimeDate = @curTimeDate AND
  101. ResourceName = @curResourceName AND
  102. ChargeDesc = @curChargeDesc AND
  103. AbHrs = @curAbsenceHours)+ (@Looper + @AdjustDay)
  104. --
  105. -- This is to create additional required records but also, check the proposed date
  106. -- against the dbo.calendar and increment the date, if necessary, to ensure the new
  107. -- record contains the date of a valid working day.
  108. --
  109. WHILE @Looper <= (@RecCounter-1)
  110.  
  111. INSERT INTO Absences
  112. (
  113. TimeDate,
  114. MonthNum,
  115. ResourceName,
  116. Studio_Company,
  117. ChargeDesc,
  118. AbHrs
  119. )
  120. (SELECT
  121. @AbDate,
  122. MONTH(@AbDate),
  123. ResourceName,
  124. Studio_Company,
  125. ChargeDesc,
  126. @AbsenceHours
  127. FROM dbo.Absenceview
  128. WHERE TimeDate = @curTimeDate AND
  129. ResourceName = @curResourceName AND
  130. ChargeDesc = @curChargeDesc AND
  131. AbHrs = @curAbsenceHours );
  132.  
  133. -- Check the next date to see if it is a valid WorkDay by looking up proposed date in dbo.Calendar
  134. -- Confused as to the order of these events. I want it to stop incrementing @AdjustDay if the
  135. -- @DateCheck = 'Y' so that it can be used.
  136.  
  137. WHILE @DateCheck = 'N'
  138. BEGIN
  139. SET @AdjustDay = @AdjustDay + 1
  140.  
  141. SET @abDate = @abDate + (@Looper+@AdjustDay)
  142.  
  143. SET @DateCheck = (SELECT dbo.Calendar.WorkingDay FROM dbo.Calendar WHERE
  144. dbo.Calendar.CalDate = @abDate)
  145. END
  146.  
  147. --
  148. -- Once the first sets of Absence records have been created with the value of @AbsenceHouse,
  149. -- the last timesheet to create will be created with the value of @LastRec
  150. ---
  151. INSERT INTO Absences
  152. (
  153. TimeDate,
  154. MonthNum,
  155. ResourceName,
  156. Studio_Company,
  157. ChargeDesc,
  158. AbHrs
  159. )
  160. (
  161. SELECT
  162. @AbDate,
  163. MONTH(@AbDate),
  164. ResourceName,
  165. Studio_Company,
  166. ChargeDesc,
  167. @LastRec
  168. FROM dbo.Absenceview
  169. WHERE TimeDate = @curTimeDate AND
  170. ResourceName = @curResourceName AND
  171. ChargeDesc = @curChargeDesc AND
  172. AbHrs = @curAbsenceHours );
  173. END
  174. ELSE
  175. BEGIN
  176. --
  177. -- This is what happens when there is only one Absence timesheet. It is to create a single
  178. -- absence record as it is in the Absenceview without additional records created.
  179. --
  180. INSERT INTO dbo.Absences
  181. (
  182. TimeDate,
  183. MonthNum,
  184. ResourceName,
  185. Studio_Company,
  186. ChargeDesc,
  187. AbHrs
  188. )
  189. (
  190. SELECT
  191. TimeDate,
  192. MonthNum,
  193. ResourceName,
  194. Studio_Company,
  195. ChargeDesc,
  196. AbHrs
  197. FROM dbo.Absenceview
  198. WHERE TimeDate = @curTimeDate AND
  199. ResourceName = @curResourceName AND
  200. ChargeDesc = @curChargeDesc AND
  201. AbHrs = @curAbsenceHours );
  202. END
  203.  
  204. FETCH NEXT FROM @absence_cursor
  205. INTO @curTimeDate,@curResourceName,@curChargeDesc,@curAbsenceHours
  206.  
  207. END
  208.  
  209. CLOSE @absence_cursor
  210.  
  211. DEALLOCATE @absence_cursor
Reply With Quote Quick reply to this message  
Reply

Message:


Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC