Performing operations in a Pivot - sql-server

I am trying to implement a PIVOT but I am having trouble performing basic operations in it.
Current table:
week_no username days pick_count duration
------------------------------------------------
Week 50 Beck W Wednesday 227 7978
Week 50 Beck W Friday 320 7481
Week 50 Beck W Friday 282 5718
Week 50 Cockram D Thursday 165 10478
Week 50 Cowell P Thursday 145 14403
Week 50 Cowell P Thursday 159 7450
Week 50 Cowell P Friday 217 13101
...
Expected result:
week_no username monday tuesday wednesday thursday friday saturday sunday
--------------------------------------------------------------------------
Week 50 Beck W NULL NULL 102 NULL 164 NULL NULL
Week 50 Cockram D NULL NULL NULL 56 NULL NULL NULL
Week 50 Cowell P NULL NULL NULL 50 59 NULL NULL
...
The expected result should be calculated as followed: pick_count * 3600 / duration. That is the calculation I am having problem computing. When PIVOTing like so
SELECT
*
FROM
(
SELECT
week_no,
username,
days,
pick_count,
duration
FROM
table
) AS src
PIVOT
(
SUM(pick_count) * 3600 / SUM(duration) FOR days IN (monday, tuesday, wednesday, thursday, friday, saturday, sunday)
) AS pvt
I get Incorrect syntax near '*'.

PIVOT is not very flexible.
You can just use the old style cross tab approach.
SELECT week_no,
username,
SUM(CASE WHEN days = 'monday' then pick_count end) * 3600
/ SUM(CASE WHEN days = 'monday' then duration end) as monday,
SUM(CASE WHEN days = 'tuesday' then pick_count end) * 3600
/ SUM(CASE WHEN days = 'tuesday' then duration end) as tuesday
/*TODO: Add other five days*/
FROM YourTable
GROUP BY week_no,
username

I eventually found what I was looking for. Indeed, all I needed to do was to compute the calculation in the SELECT instead of the PIVOT.
SELECT
*
FROM
(
SELECT
week_no,
username,
days,
SUM(pick_count) * 3600 / SUM(duration) AS pick_rate
FROM
table
GROUP BY
week_no,
username,
days
) AS src
PIVOT
(
MAX(pick_rate) FOR days IN (monday, tuesday, wednesday, thursday, friday, saturday, sunday)
) AS pvt

Related

Find totals for weektodate,monthtodate from sql server tables

I'm trying to get total number of applications made for current day (Monday) to (Last Monday) , and Tuesday to Last week Tuesday and so on. Also, I would like to get applications made for this Month (Month to date ). Please help
I'm using SQL Server 2008 R2
Category Date Day Applications
CASS 16/09/2019 Monday 1
CASS 16/09/2019 Monday 3
RBS 16/09/2019 Monday 1
RBS 16/09/2019 Monday 3
RBS 16/09/2019 Monday 14
RBS 16/09/2019 Monday 15
CASS 23/09/2019 Monday 2
CASS 23/09/2019 Monday 1
CASS 23/09/2019 Monday 2
CASS 23/09/2019 Monday 1
CASS 23/09/2019 Monday 8
RBS 23/09/2019 Monday 3
RBS 23/09/2019 Monday 3
Output:
23/09/2019
CASS: 14
Previous week: 14-4=10
RBS: 6
Previous week: 6-33= -27
Month to date(Total aplications till date): 57
Using LEAD() function you could achieve what you looking for, have a look at following example, you may want adjust PARTITION BY clause and sub-query as per your requirements:
Query Result..
SELECT T.*,
LEAD (AppCount) OVER (PARTITION BY cDay ORDER BY weekNum) as PrevAppCount,
T.AppCount - LEAD (AppCount) OVER (PARTITION BY cDay ORDER BY weekNum)
FROM (
select Category,
datepart(week,cDate) as weekNum,
cDay,
sum (AppCount) as AppCount
from MyTable
Group by Category, Datepart(week,cDate),cDay
) AS T
You can write query like this:
;with cte as (
select *, rown = ROW_NUMBER() over(partition by category order by [Date]) from (
select category, [Date], sum(applications) appcnt from #table
group by category, [Date]
) t
)
Select case when nextweek.Category is null then curweek.Category else
curweek.Category + ' Previous week' end ,
case when nextweek.Category is not null then nextweek.appcnt - curweek.appcnt else curweek.appcnt end
from cte curweek
left join cte nextweek on curweek.rown = nextweek.rown -1
and curweek.Category = nextweek.Category
union all
select 'Month to date', sum(applications) from #table
code:
https://rextester.com/ABI84558

Changing timesheet punch in and out query to a crosstab query

I am looking to create a crosstab query for a timeclock website I've made. Currently I'm just displaying the result in a table with each day as it's own line.
This is an example of the data.
id type user time
4941 1 user1 2017-10-03 11:24:00
4954 2 user1 2017-10-03 14:43:00
4955 1 user1 2017-10-03 14:43:00
4967 2 user1 2017-10-03 16:00:00
And here is the query that calculates the data for the current week.
SELECT user as UserName, CONVERT (varchar(10), time, 101) AS Date,
SUM(
CASE WHEN type = 1
THEN - 1 * (datepart(hh , [time]) + datepart(mi , [time]) / 60.0)
ELSE datepart(hh , [time]) + datepart(mi , [time]) / 60.0 END) AS Total
FROM table WHERE (username LIKE 'user1')
and datepart(wk, [time]) = datepart(wk, GETDATE())
GROUP BY user, CONVERT (varchar(10), time, 101) ORDER BY Date DESC
This displays data just like I wanted.
UserName Date Total
user1 08/21/2019 4.316667
user1 08/20/2019 9.366666
user1 08/19/2019 8.283333
However now I want to take that data and put it into a crosstab query so I can show the weeks on each row with the daily data in columns on that row. So far I've tried using a pivot to accomplish this.
SELECT Year, Month, Week, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
FROM (SELECT DATENAME(WEEKDAY, CONVERT (varchar(10), time, 101)) DAY, DATEPART(wk, CONVERT (varchar(10), _time, 101)) as Week
, DATEPART(M, CONVERT (varchar(10), time, 101)) as Month, DATEPART(YYYY, CONVERT (varchar(10), time, 101)) as Year
, SUM(
CASE
WHEN type = 1
THEN - 1 * (datepart(hh , [time]) + datepart(mi , [time]) / 60.0)
ELSE datepart(hh , [time]) + datepart(mi , [time]) / 60.0
END) AS Total
FROM table WHERE (username LIKE 'user1')
GROUP BY CONVERT(varchar(10), time, 101) ) p
PIVOT (SUM(Total)
FOR DAY IN (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday) ) pvt
ORDER BY Year, Month, Week DESC
And I have some success. The data seems to be displaying correctly. However when I try to ORDER BY more than one variable the display order is out of whack.
Year Month Week Monday Tuesday Wednesday Thursday Friday Saturday Sunday
2017 10 40 NULL 4.600000 0.000000 NULL NULL NULL NULL
2018 3 11 0.966667 NULL NULL NULL NULL NULL 5.150000
2019 7 31 NULL NULL 8.116667 NULL NULL NULL NULL
2019 8 34 8.283333 9.366666 -7.483333 NULL NULL NULL NULL
2019 8 33 8.166667 8.266667 8.083333 8.616668 8.883334 NULL NULL
2019 8 32 8.350000 8.333333 8.466666 7.883333 7.516666 NULL NULL
2019 8 31 NULL NULL NULL 8.833334 8.000001 NULL NULL
It should be sorting by Year, Week and Month. When I do just the year it works orders fine. But If I add in Week and Month it jumbles up the data in the wrong order. What am I doing wrong? It should look like this.
Year Week Month Monday Tuesday Wednesday Thursday Friday Saturday Sunday
2019 34 8 8.283333 9.366666 -7.483333 NULL NULL NULL NULL
2019 33 8 8.166667 8.266667 8.083333 8.616668 8.883334 NULL NULL
2019 32 8 8.350000 8.333333 8.466666 7.883333 7.516666 NULL NULL
2019 31 8 NULL NULL NULL 8.833334 8.000001 NULL NULL
2019 31 7 NULL NULL 8.116667 NULL NULL NULL NULL
2018 11 3 0.966667 NULL NULL NULL NULL NULL 5.150000
2017 40 10 NULL 4.600000 0.000000 NULL NULL NULL NULL
Also, how can I sum the week value to a totals column?

T-SQL Calculate recurrences of a Date

I am working on a CTE which calculate the recurrences of a Week but I am having some problems when the pattern cross the year.
The CTE should
Calculate all occurrences based on the following parameters:
Recurrence Count - how many times it will happen
Week Days - in which day of the week it will happen
Start Date - when the pattern calculation will start
Periodicity - How often in terms of weeks, i.e. 1 every week, 2 every 2 weeks
Starting Week - The Week number of the First Occurrence, which reflects the Start Date column
This is how I store the patterns:
/*
Pattern Table
*/
CREATE TABLE Pattern (
[Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY
, [Subject] [nvarchar](100) NULL
, [RecurrenceCount] [int] NULL
, [WeekDays] [varchar](max) NULL
, [StartDate] [datetime] NULL
, [EndDate] [datetime] NULL
, [Periodicity] [int] NULL
, [StartingWeek] [int] NULL
);
Below is a couple of patterns I am using to test my CTE:
/*
Pattern samples for test
*/
Insert into Pattern Values (N'Every 5 Weeks Fri, Sat, Sun', 72, 'Friday, Saturday, Sunday', N'2016-12-02', N'2016-12-02', 5, datepart(wk, N'2016-12-02'));
Insert into Pattern Values (N'Every 3 Weeks Tue, Wed, Thu', 20, 'Tuesday, Wednesday, Thursday', N'2016-11-01', N'2016-11-01', 3, datepart(wk, N'2016-11-01'));
I start counting considering first day of week Monday
SET DATEFIRST 1
And this is the CTE I am using to run this calculations:
/*
Display Patterns
*/
select * from Pattern
DECLARE #mindate DATE = (SELECT MIN(StartDate) FROM Pattern)
DECLARE #maxmindate DATE = (SELECT MAX(StartDate) FROM Pattern)
DECLARE #maxcount INT = (SELECT MAX(RecurrenceCount) FROM Pattern)
DECLARE #maxdate DATE = DATEADD(WK, #maxcount + 10, #maxmindate)
/*
CTE to generate required occurrences
*/
;With cteKeyDate As (
Select
KeyStartDate = #MinDate,
KeyDOW = DateName(WEEKDAY, #MinDate),
KeyWeek = datepart(WK,#MinDate)
Union All
Select
KeyStartDate = DateAdd(DD, 1, df.KeyStartDate) ,
KeyDOW = DateName(WEEKDAY,DateAdd(DD, 1, df.KeyStartDate)),
KeyWeek= DatePart(WK,DateAdd(DD, 1, df.KeyStartDate))
From cteKeyDate DF
Where DF.KeyStartDate <= #MaxDate
)
SELECT
Id, KeyStartDate, KeyDow, KeyWeek, RowNr, OccNr = ROW_NUMBER() OVER (PARTITION BY Id ORDER BY StartDate)
FROM
(Select
A.Id
,A.StartDate
,A.EndDate
,Count = A.RecurrenceCount
,Days = A.WeekDays
,Every = A.Periodicity
,KeyStartDate = CASE
/*
if no periodicity (1) then it is sequential
if periodicity, first week doesn't apply (MIN KeyWeek)
*/
WHEN A.Periodicity = 1
OR ( Periodicity <> 1 AND (SELECT MIN(C.StartingWeek) FROM Pattern AS C WHERE C.Id = A.Id) = KeyWeek )
THEN KeyStartDate
/* Otherwise formula ADD WEEKS => Current Week Min Week */
ELSE
DATEADD( WK, ((A.Periodicity - 1) * ( KeyWeek - (SELECT MIN(C.StartingWeek) FROM Pattern AS C WHERE C.Id = A.Id) ) ) , KeyStartDate )
END
,KeyDow
,KeyWeek
,RowNr = Row_Number() over (Partition By A.Id Order By B.KeyStartDate)
,Periodicity = A.Periodicity
from
Pattern A
Join cteKeyDate B on B.KeyStartDate >= DATEADD(DAY, -1, A.StartDate) and Charindex(KeyDOW, A.WeekDays) > 0
) Final
Where
RowNr <= Count AND Id = 1
Option (maxrecursion 32767)
Now, if I test again my patterns, for example, the first one, I get this result, which has the bug when the occurrences happen in the next year. The RowNr 15 is wrong because it should happen on 23 of April (Sunday) and not the next week.
Id KeyStartDate KeyDow KeyWeek RowNr OccNr
1 02.12.2016 Friday 49 1 1
2 03.12.2016 Saturday 49 2 2
3 04.12.2016 Sunday 49 3 3
4 06.01.2017 Friday 50 4 4
5 07.01.2017 Saturday 50 5 5
6 08.01.2017 Sunday 50 6 6
7 10.02.2017 Friday 51 7 7
8 11.02.2017 Saturday 51 8 8
9 12.02.2017 Sunday 51 9 9
10 17.03.2017 Friday 52 10 10
11 18.03.2017 Saturday 52 11 11
12 19.03.2017 Sunday 52 12 12
13 21.04.2017 Friday 53 13 13
14 22.04.2017 Saturday 53 14 14
15 28.04.2013 Sunday 1 15 15
16 31.05.2013 Friday 2 16 16
17 01.06.2013 Saturday 2 17 17
While the second pattern is calculated just fine. I think I have a problem in the logic when the pattern cross the year and the number of weeks reset to 0 in SQL but I cannot find a solution, I struggled now for few days.
You can execute the code with the samples here.
Spend some time on this. Your calculation used is flawed. Unless there is special rules not indicated in your question I do not see why some dates are special. I prefer to use variable tables.
/*
Pattern Table
*/
DECLARE #Pattern TABLE(
[Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY
,[Subject] [nvarchar](100) NULL
,[RecurrenceCount] [int] NULL
,[WeekDays] [varchar](max) NULL
,[StartDate] [datetime] NULL
,[EndDate] [datetime] NULL
,[Periodicity] [int] NULL
,[StartingWeek] [int] NULL
);
/*
Populate with values based on Recurreance and Startdate. The startdate will give the start week, which make the start week obsolete.
*/
DECLARE #PreferredDate TABLE(
[Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY
,[PreferredDate] [datetime] NULL
,[PreferredWeek] [int] NULL
,[PreferredYear] [int] NULL
)
It is very important to always retrieve the current setting for datefirst. You will break someone else's calculation if they use another setting. I have also added the pattern id for obvious reasons.
DECLARE #DateFirst int = ##dateFirst --DATEFIRST is a global setting
DECLARE #mindate DATE = (SELECT MIN(StartDate) FROM #Pattern WHERE id=#PreferredSubjectID)
DECLARE #maxmindate DATE = (SELECT MAX(StartDate) FROM #Pattern WHERE Id=#PreferredSubjectID)
DECLARE #maxcount INT = (SELECT MAX(RecurrenceCount) FROM #Pattern WHERE Id=#PreferredSubjectID)
DECLARE #maxdate DATE = DATEADD(WK, #maxcount + 50, #maxmindate)
SET DATEFIRST 1
DECLARE #PreferredSubjectID int = 1
The #preferreddate table is populated using the following:
/*
CTE to generate required preferred dates
*/
;With ctePreferredDate AS (
Select PreferredDate = #MinDate, PreferredWeek = DATEPART(WK, #MinDate), PreferredYear = DATEPART(YYYY, #MinDate)
Union All
SELECT PreferredDate = DATEADD(WK,(SELECT Periodicity FROM #Pattern WHERE Id=#PreferredSubjectID), PreferredDate)
,PreferredWeek = DATEPART(WK,DATEADD(WK,(SELECT Periodicity FROM #Pattern WHERE Id=#PreferredSubjectID), PreferredDate))
,PreferredYear = DATEPART(yyyy,DATEADD(WK,(SELECT Periodicity FROM #Pattern WHERE Id=#PreferredSubjectID), PreferredDate))
From ctePreferredDate pFD
Where pFD.PreferredDate <= #MaxDate
)
INSERT INTO #PreferredDate (PreferredDate, PreferredWeek, PreferredYear)
SELECT PreferredDate, PreferredWeek, PreferredYear
FROM ctePreferredDate
The final CTE table is populated using the following:
/*
CTE to generate required occurrences
*/
;With cteKeyDate As (
Select KeyStartDate = #MinDate
,KeyDOW = DateName(WEEKDAY, #MinDate)
,KeyWeek = datepart(WK,#MinDate)
,id = #PreferredSubjectID
,KeyOccurrance = #maxcount
Union All
Select KeyStartDate = DateAdd(DD, 1, df.KeyStartDate)
,KeyDOW = DateName(WEEKDAY,DateAdd(DD, 1, df.KeyStartDate))
,KeyWeek= DatePart(WK,DateAdd(DD, 1, df.KeyStartDate))
,id=#PreferredSubjectID
,KeyOccurrance = #maxcount
From cteKeyDate DF
Where DF.KeyStartDate <= #MaxDate
)
SELECT StartDate
,[DayOfWeek]
,[Week]
,OccNr = ROW_NUMBER() OVER (PARTITION BY Id ORDER BY StartDate)
FROM
(
SELECT cte.KeyStartDate AS StartDate
,cte.KeyDOW AS [DayOfWeek]
,cte.KeyWeek AS [Week]
,cte.id
,cte.KeyOccurrance AS Occurrance
,RowNr = ROW_NUMBER() OVER (PARTITION BY KeyOccurrance ORDER BY KeyStartDate)
FROM cteKeyDate cte
INNER JOIN
#PreferredDate pfd
ON cte.KeyWeek = pfd.PreferredWeek
AND YEAR(cte.KeyStartDate) = pfd.PreferredYear
WHERE cte.KeyDOW IN (SELECT LTRIM(RTRIM(Item)) FROM fn_SplitString((SELECT weekdays from #Pattern WHERE Id=1),','))
)cte
WHERE cte.RowNr <= cte.Occurrance
ORDER BY cte.StartDate
Option (maxrecursion 32767)
SET DATEFIRST #DateFirst --Quite important
Results
2016/12/02 Friday 49 1
2016/12/03 Saturday 49 2
2016/12/04 Sunday 49 3
2017/01/06 Friday 2 4
2017/01/07 Saturday 2 5
2017/01/08 Sunday 2 6
2017/02/10 Friday 7 7
2017/02/11 Saturday 7 8
2017/02/12 Sunday 7 9
2017/03/17 Friday 12 10
2017/03/18 Saturday 12 11
2017/03/19 Sunday 12 12
2017/04/21 Friday 17 13
2017/04/22 Saturday 17 14
2017/04/23 Sunday 17 15
2017/05/26 Friday 22 16
2017/05/27 Saturday 22 17
2017/05/28 Sunday 22 18
2017/06/30 Friday 27 19
2017/07/01 Saturday 27 20
2017/07/02 Sunday 27 21
2017/08/04 Friday 32 22
2017/08/05 Saturday 32 23
2017/08/06 Sunday 32 24
2017/09/08 Friday 37 25
2017/09/09 Saturday 37 26
2017/09/10 Sunday 37 27
2017/10/13 Friday 42 28
2017/10/14 Saturday 42 29
2017/10/15 Sunday 42 30
2017/11/17 Friday 47 31
2017/11/18 Saturday 47 32
2017/11/19 Sunday 47 33
2017/12/22 Friday 52 34
2017/12/23 Saturday 52 35
2017/12/24 Sunday 52 36
2018/01/26 Friday 4 37
2018/01/27 Saturday 4 38
2018/01/28 Sunday 4 39
2018/03/02 Friday 9 40
2018/03/03 Saturday 9 41
2018/03/04 Sunday 9 42
2018/04/06 Friday 14 43
2018/04/07 Saturday 14 44
2018/04/08 Sunday 14 45
2018/05/11 Friday 19 46
2018/05/12 Saturday 19 47
2018/05/13 Sunday 19 48
2018/06/15 Friday 24 49
2018/06/16 Saturday 24 50
2018/06/17 Sunday 24 51
2018/07/20 Friday 29 52
2018/07/21 Saturday 29 53
2018/07/22 Sunday 29 54
2018/08/24 Friday 34 55
2018/08/25 Saturday 34 56
2018/08/26 Sunday 34 57
2018/09/28 Friday 39 58
2018/09/29 Saturday 39 59
2018/09/30 Sunday 39 60
2018/11/02 Friday 44 61
2018/11/03 Saturday 44 62
2018/11/04 Sunday 44 63
2018/12/07 Friday 49 64
2018/12/08 Saturday 49 65
2018/12/09 Sunday 49 66
2019/01/11 Friday 2 67
2019/01/12 Saturday 2 68
2019/01/13 Sunday 2 69
2019/02/15 Friday 7 70
2019/02/16 Saturday 7 71
2019/02/17 Sunday 7 72
The splitstring function:
ALTER FUNCTION [dbo].[fn_SplitString](
#InputStr varchar(Max),
#Seperator varchar(10))
RETURNS #OutStrings TABLE (ItemNo int identity(1,1), Item varchar(256))
AS
BEGIN
DECLARE #Str varchar(2000),
#Poz int, #cnt int
--DECLARE #OutStrings TABLE (Item varchar(2000))
SELECT #Poz = CHARINDEX (#Seperator, #InputStr), #cnt = 0
WHILE #Poz > 0 AND #cnt <= 10000
BEGIN
SELECT #Str = SubString(#InputStr, 1, #Poz - 1)
INSERT INTO #OutStrings(Item) VALUES(#Str)
SELECT #InputStr = Right(#Inputstr, Len(#InputStr) - (len(#Str) + len(#Seperator)))
SELECT #Poz = CHARINDEX (#Seperator, #InputStr), #cnt = #cnt + 1
END
IF #InputStr <> ''
BEGIN
INSERT INTO #OutStrings(Item) VALUES(#InputStr)
END
RETURN
END
The reason you are getting that issue is you are using the datepart for getting the week numbers, so once the year changes the datepart goes back to 1. This should be changed...
I made this change and The dates now get in the order of sequence, check this out.
The change is the first CTE by the way.
/*
Display Patterns
*/
select * from Pattern
DECLARE #mindate DATE = (SELECT MIN(StartDate) FROM Pattern)
DECLARE #maxmindate DATE = (SELECT MAX(StartDate) FROM Pattern)
DECLARE #maxcount INT = (SELECT MAX(RecurrenceCount) FROM Pattern)
DECLARE #maxdate DATE = DATEADD(WK, #maxcount + 10, #maxmindate)
declare #minWeekPart INT = DATEPART(WK,#MinDate)
/*
CTE to generate required occurrences
*/
;With cteKeyDate As (
Select
KeyStartDate = #MinDate,
KeyDOW = DateName(WEEKDAY, #MinDate),
KeyWeek = #minWeekPart
Union All
Select
KeyStartDate = DateAdd(DD, 1, df.KeyStartDate) ,
KeyDOW = DateName(WEEKDAY,DateAdd(DD, 1, df.KeyStartDate)),
KeyWeek= #minWeekPart + datediff(WK,#MinDate,DateAdd(DD, 1, df.KeyStartDate))
From cteKeyDate DF
Where DF.KeyStartDate <= #MaxDate
)
--select * from cteKeyDate
-- order by 1
--Option (maxrecursion 32767)
SELECT
Id, KeyStartDate, KeyDow, KeyWeek, RowNr, OccNr = ROW_NUMBER() OVER (PARTITION BY Id ORDER BY StartDate)
FROM
(Select
A.Id
,A.StartDate
,A.EndDate
,Count = A.RecurrenceCount
,Days = A.WeekDays
,Every = A.Periodicity
,KeyStartDate = CASE
/*
if no periodicity (1) then it is sequential
if periodicity, first week doesn't apply (MIN KeyWeek)
*/
WHEN A.Periodicity = 1
OR ( Periodicity <> 1 AND (SELECT MIN(C.StartingWeek) FROM Pattern AS C WHERE C.Id = A.Id) = KeyWeek )
THEN KeyStartDate
/* Otherwise formula ADD WEEKS => Current Week Min Week */
ELSE
DATEADD( WK, ((A.Periodicity - 1) * ( KeyWeek - (SELECT MIN(C.StartingWeek) FROM Pattern AS C WHERE C.Id = A.Id) ) ) , KeyStartDate )
END
,KeyDow
,KeyWeek
,RowNr = Row_Number() over (Partition By A.Id Order By B.KeyStartDate)
,Periodicity = A.Periodicity
from
Pattern A
Join cteKeyDate B on B.KeyStartDate >= DATEADD(DAY, -1, A.StartDate) and Charindex(KeyDOW, A.WeekDays) > 0
) Final
Where
RowNr <= Count AND Id = 1
order by 2
Option (maxrecursion 32767)
I did run it in the rextester and you can find it here --> http://rextester.com/GWEY37271

get total orders for the last 1 month every week

I have an "Orders" table containing column CreatedDate (datetime) on when the order took place.
Today is Feb 13, 2014.
How to get total records for the last 4 weeks for every week.
it should return something like this:
PerDate Total
2014-01-26 13 <--- sunday
2014-02-02 24 <--- sunday
2014-02-09 33 <--- sunday
2014-02-13 35 <--- this is today
13 from the first record is the total record from 2014-01-20 00:00:00 AM (monday) to 2014-01-26 12:00:00 PM (sunday)
24 from the 2nd record is the total record from 2014-01-27 00:00:00 AM (monday) to 2014-02-02 12:00:00 PM (sunday)
33 from the 3rd record is the total record from 2014-02-03 00:00:00 AM (monday) to 2014-02-09 12:00:00 PM (sunday)
35 from the 4th record is the total record from 2014-02-10 00:00:00 AM (monday) to 2014-02-13 (today)
so they are in Ascending order.
You should use DATEPART(dw,CreatedDate) function to calculate date of begin and end of the week for each CreatedDate and then just group by this field:
WITH T AS
(
SELECT
cast(floor(cast(CreatedDate as float)) as datetime)
-DATEPART(dw,CreatedDate)+1 as BeginOfweek,
cast(floor(cast(CreatedDate as float)) as datetime)
-DATEPART(dw,CreatedDate)+8 as EndOfWeek
FROM ORDERS
WHERE cast(floor(cast(CreatedDate as float)) as datetime) BETWEEN
DATEADD(WEEK,-4,GETDATE())
AND
GETDATE()
)
SELECT
BeginOfWeek,
MIN(CASE WHEN GETDATE()<EndOfWeek
THEN GETDATE()
ELSE EndOfWeek
END) as EndOfWeek,
Count(*) as OrdersCount
FROM T
Group by BeginOfWeek
SQLFiddle demo

Calculate total running time from start/stop timestamps

I have a table containing a number of timestamps per day, they represents start and stop events.
ID TimeStamp
----------------------
1 2008-01-01 07:00:00
1 2008-01-01 08:15:00
1 2008-01-01 10:00:00
1 2008-01-01 11:00:00
1 2008-01-02 10:30:00
1 2008-01-02 12:00:00
I would like to calcuate the total running time per day, like this:
ID Date RunningTime
-------------------------
1 2008-01-01 02:15:00
1 2008-01-02 01:30:00
Do anyone have a nice T-SQL solution for my problem?
WITH q AS
(
SELECT *,
CONVERT(DATETIME, CONVERT(VARCHAR(8), TimeStamp, 112), 112) AS dte,
ROW_NUMBER() OVER (PARTITION BY id, CONVERT(DATETIME, CONVERT(VARCHAR(8), TimeStamp, 112), 112) ORDER BY TimeStamp) AS rn
FROM mytable
)
SELECT qb.id, qb.dte, SUM(DATEDIFF(second, qb.TimeStamp, qe.TimeStamp))
FROM q qb
JOIN q qe
ON qe.id = qb.id
AND qe.dte = qb.dte
AND qe.rn = qb.rn + 1
WHERE qb.rn % 2 = 1
GROUP BY
qb.id, qb.dte
This assumes that every record open on a certain day should also be closed on the same day.

Resources