I am trying to "flatten" a delivery schedule table from many rows for one customer into one row per customer. Each customer can have from 1 to 7 LeadDays, OrderDays, and DeliveryDays.
This is what I have to work with:
CustomerNumber | Company | Year | WeekNumber | OrderDate | OrderDayName | LeadDays | DeliveryDate | DeliveryDayName
--------------------------------------------------------------------------------------------------------------
5002 | Comp_A | 2022 | 15 | 2022-04-03 | Sunday | 1.0 | 2022-04-04 | Monday
5002 | Comp_A | 2022 | 15 | 2022-04-04 | Monday | 1.0 | 2022-04-05 | Tuesday
5002 | Comp_A | 2022 | 15 | 2022-04-05 | Tuesday | 1.0 | 2022-04-06 | Wednesday
5002 | Comp_A | 2022 | 15 | 2022-04-06 | Wednesday | 1.0 | 2022-04-07 | Thursday
5002 | Comp_A | 2022 | 15 | 2022-04-07 | Thursday | 1.0 | 2022-04-08 | Friday
5002 | Comp_A | 2022 | 15 | 2022-04-08 | Friday | 1.0 | 2022-04-09 | Saturday
5002 | Comp_A | 2022 | 15 | 2022-04-09 | Saturday | 1.0 | 2022-04-10 | Sunday
310365 | Comp_A | 2022 | 15 | 2022-04-05 | Tuesday | 1.0 | 2022-04-06 | Wednesday
310365 | Comp_A | 2022 | 15 | 2022-04-07 | Thursday | 1.0 | 2022-04-08 | Friday
310428 | Comp_A | 2022 | 15 | 2022-04-06 | Wednesday | 1.0 | 2022-04-07 | Thursday
19401 | Comp_B | 2022 | 15 | 2022-04-04 | Monday | 1.0 | 2022-04-05 | Tuesday
19401 | Comp_B | 2022 | 15 | 2022-04-05 | Tuesday | 1.0 | 2022-04-06 | Wednesday
19401 | Comp_B | 2022 | 15 | 2022-04-06 | Wednesday | 1.0 | 2022-04-07 | Thursday
19401 | Comp_B | 2022 | 15 | 2022-04-07 | Thursday | 1.0 | 2022-04-08 | Friday
19401 | Comp_B | 2022 | 15 | 2022-04-08 | Friday | 1.0 | 2022-04-09 | Saturday
.....and this is what I need it to look like:
CustomerNumber | Company | Year | WeekNumber | LeadDays_1 | OrderDate_1 | DeliveryDate_1 | LeadDays_2 | OrderDate_2 | DeliveryDate_2 | LeadDays_3 | OrderDate_3 | DeliveryDate_3 | LeadDays_4 | OrderDate_4 | DeliveryDate_4 | LeadDays_5 | OrderDate_5 | DeliveryDate_5 | LeadDays_6 | OrderDate_6 | DeliveryDate_6 | LeadDays_7 | OrderDate_7 | DeliveryDate_7
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5002 | Comp_A | 2022 | 15 | 1.0 | 2022-04-03 | 2022-04-04 | 1.0 | 2022-04-04 | 2022-04-05 | 1.0 | 2022-04-05 | 2022-04-06 | 1.0 | 2022-04-06 | 2022-04-07 | 1.0 | 2022-04-07 | 2022-04-08 | 1.0 | 2022-04-08 | 2022-04-09 | 1.0 | 2022-04-09 | 2022-04-10
310365 | Comp_A | 2022 | 15 | 1.0 | 2022-04-05 | 2022-04-06 | 1.0 | 2022-04-07 | 2022-04-08 | | | | | | | | | | | | | | |
310428 | Comp_A | 2022 | 15 | 1.0 | 2022-04-06 | 2022-04-07 | | | | | | | | | | | | | | | | | |
19401 | Comp_B | 2022 | 15 | 1.0 | 2022-04-04 | 2022-04-05 | 1.0 | 2022-04-05 | 2022-04-06 | 1.0 | 2022-04-06 | 2022-04-07 | 1.0 | 2022-04-07 | 2022-04-08 | 1.0 | 2022-04-08 | 2022-04-09 | | | | | |
I know it should be a (relatively simple?) PIVOT table, but I can't seem to wrap my head around it.
You can do conditional aggregation using MAX(CASE which is much more flexible than PIVOT. In your case, you first need to generate a row-number to pivot over
SELECT
CustomerNumber,
Company,
Year,
WeekNumber,
MAX(CASE WHEN rn = 1 THEN LeadDays END) LeadDays_1,
MAX(CASE WHEN rn = 1 THEN OrderDate END) OrderDate_1,
MAX(CASE WHEN rn = 1 THEN DeliveryDate END) DeliveryDate_1,
MAX(CASE WHEN rn = 2 THEN LeadDays END) LeadDays_2,
MAX(CASE WHEN rn = 2 THEN OrderDate END) OrderDate_2,
MAX(CASE WHEN rn = 2 THEN DeliveryDate END) DeliveryDate_2,
MAX(CASE WHEN rn = 3 THEN LeadDays END) LeadDays_3,
MAX(CASE WHEN rn = 3 THEN OrderDate END) OrderDate_3,
MAX(CASE WHEN rn = 3 THEN DeliveryDate END) DeliveryDate_3,
MAX(CASE WHEN rn = 4 THEN LeadDays END) LeadDays_4,
MAX(CASE WHEN rn = 4 THEN OrderDate END) OrderDate_4,
MAX(CASE WHEN rn = 4 THEN DeliveryDate END) DeliveryDate_4,
MAX(CASE WHEN rn = 5 THEN LeadDays END) LeadDays_5,
MAX(CASE WHEN rn = 5 THEN OrderDate END) OrderDate_5,
MAX(CASE WHEN rn = 5 THEN DeliveryDate END) DeliveryDate_6
FROM (
SELECT *,
rn = ROW_NUMBER() OVER (
PARTITION BY CustomerNumber, Company, Year, WeekNumber
ORDER BY OrderDate, DeliveryDate)
FROM YourTable t
) t
GROUP BY
CustomerNumber,
Company,
Year,
WeekNumber;
db<>fiddle
I was facing this problem and spend a lot of time today. So, i thought to share it here:
I have a table where we store debitDate and we have a stored procedure where every month we set the debit date to next month in the table.
So, if its debit date is 29th Jan, 2020 -> 29th Feb, 2020 -> 29th March, 2020 - so it should go on like this. I am using DATEADD() function in the stored procedure.
But for 30th & 31st i am facing issue. It should work like below in upcoming years:
Desired Behaviour:
30th Jan, 2020 -> 29th Feb, 2020 -> 30th Mar, 2020 -> 30th Apr, 2020
30th Jan, 2021 -> 28th Feb, 2021 -> 30th Mar, 2021 -> 30th Apr, 2021
31st Jan, 2020 -> 29th Feb, 2020 -> 31st Mar, 2020 -> 30th Apr, 2020
Issue:
30th Jan, 2020 -> 29th Feb, 2020 -> 29th Mar, 2020 -> 29th Apr, 2020
30th Jan, 2021 -> 28th Feb, 2021 -> 28th Mar, 2021 -> 28th Apr, 2021
31st Jan, 2020 -> 29th Feb, 2020 -> 29th Mar, 2020 -> 29th Apr, 2020
Solution 1:
For solution i have thought i can add a new column to the table as previousDebitDate and when we update the debit date we will check, if previousDebitDate day is 30 or 31.
If true then
DATEADD(MONTH, 2, #previousDebitDate)
else
DATEADD(MONTH, 1, #debitDate)
If anyone has a better solution please feel free to post your answer.
Solution 2:
For this issue a better solution is to add debitDay as a new column to the table and save only day part (ex: 30) and calculate each month debit date on the fly.
I think Solution 2 is better! Thanks #Arvo!!!
Maybe I 've understand very well & maybe not, but here's what I think you're looking for
CREATE TABLE Data
(
Dates DATE
);
INSERT Data(Dates) VALUES
('2020-01-30');
WITH CTE AS
(
SELECT Dates,
DATEADD(Month, 1, Dates) NextMonth,
DAY(EOMONTH(DATEADD(Month, 1, Dates))) LastDay
FROM Data
UNION ALL
SELECT DATEADD(Month, 1, Dates),
DATEADD(Month, 1, NextMonth),
DAY(EOMONTH(DATEADD(Month, 1, NextMonth)))
FROM CTE
WHERE Dates <= '2021-12-31'
)
SELECT Dates, NextMonth, DATEFROMPARTS(YEAR(Dates), MONTH(NextMonth),
CASE WHEN LastDay > 30 THEN 30 ELSE LastDay END) Value
FROM CTE;
Which 'll returns:
+------------+------------+------------+
| Dates | NextMonth | Value |
+------------+------------+------------+
| 2020-01-30 | 2020-02-29 | 2020-02-29 |
| 2020-02-29 | 2020-03-29 | 2020-03-30 |
| 2020-03-29 | 2020-04-29 | 2020-04-30 |
| 2020-04-29 | 2020-05-29 | 2020-05-30 |
| 2020-05-29 | 2020-06-29 | 2020-06-30 |
| 2020-06-29 | 2020-07-29 | 2020-07-30 |
| 2020-07-29 | 2020-08-29 | 2020-08-30 |
| 2020-08-29 | 2020-09-29 | 2020-09-30 |
| 2020-09-29 | 2020-10-29 | 2020-10-30 |
| 2020-10-29 | 2020-11-29 | 2020-11-30 |
| 2020-11-29 | 2020-12-29 | 2020-12-30 |
| 2020-12-29 | 2021-01-29 | 2020-01-30 |
| 2021-01-29 | 2021-02-28 | 2021-02-28 |
| 2021-02-28 | 2021-03-28 | 2021-03-30 |
| 2021-03-28 | 2021-04-28 | 2021-04-30 |
| 2021-04-28 | 2021-05-28 | 2021-05-30 |
| 2021-05-28 | 2021-06-28 | 2021-06-30 |
| 2021-06-28 | 2021-07-28 | 2021-07-30 |
| 2021-07-28 | 2021-08-28 | 2021-08-30 |
| 2021-08-28 | 2021-09-28 | 2021-09-30 |
| 2021-09-28 | 2021-10-28 | 2021-10-30 |
| 2021-10-28 | 2021-11-28 | 2021-11-30 |
| 2021-11-28 | 2021-12-28 | 2021-12-30 |
| 2021-12-28 | 2022-01-28 | 2021-01-30 |
| 2022-01-28 | 2022-02-28 | 2022-02-28 |
+------------+------------+------------+
Much better
WITH CTE AS
(
SELECT 1 N, Dates, Dates ExpectedValue
FROM Data
UNION ALL
SELECT N+1, DATEADD(Month, 1, Dates), DATEFROMPARTS(YEAR(ExpectedValue), MONTH(DATEADD(Month, 1, ExpectedValue)),
CASE WHEN DAY(EOMONTH(DATEADD(Month, 1, ExpectedValue))) > 30 THEN 30
ELSE DAY(EOMONTH(DATEADD(Month, 1, ExpectedValue)))
END)
FROM CTE
WHERE N < 15
)
SELECT *
FROM CTE
ORDER BY N;
Returns:
+----+------------+---------------+
| N | Dates | ExpectedValue |
+----+------------+---------------+
| 1 | 2020-01-30 | 2020-01-30 |
| 2 | 2020-02-29 | 2020-02-29 |
| 3 | 2020-03-29 | 2020-03-30 |
| 4 | 2020-04-29 | 2020-04-30 |
| 5 | 2020-05-29 | 2020-05-30 |
| 6 | 2020-06-29 | 2020-06-30 |
| 7 | 2020-07-29 | 2020-07-30 |
| 8 | 2020-08-29 | 2020-08-30 |
| 9 | 2020-09-29 | 2020-09-30 |
| 10 | 2020-10-29 | 2020-10-30 |
| 11 | 2020-11-29 | 2020-11-30 |
| 12 | 2020-12-29 | 2020-12-30 |
| 13 | 2021-01-29 | 2020-01-30 |
| 14 | 2021-02-28 | 2020-02-29 |
| 15 | 2021-03-28 | 2020-03-30 |
+----+------------+---------------+
Here is a db<>fiddle
I need to get start and end date for each week in given month/year. (month and year are always given - like march 2017).
Example, january 2017:
1 week : '2017-01-01' - '2017-01-01'
2 week: '2017-01-02' - '2017-01-08'
3 week: '2017-01-09' - '2017-01-15'
4 week: '2017-01-16' - '2017-01-22'
5 week: '2017-01-23' - '2017-01-29'
6 week: '2017-01-30' - '2017-01-31'
I already know how to get number of weeks for given month / year:
select *,
DATEDIFF(WEEK, DATEADD(day,-1,StartAt), DATEADD(day,-1,EndAt)) +1
as NumWeeks
But how to get start / end date for each week for the given month/year?
If you just want a function to return the weeks of a month for one month then this would do what you want:
create function dbo.udf_weeks_of_month (#fromdate date)
returns table as return (
with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, dates as (
select top (datediff(day, #fromdate, dateadd(month, datediff(month, 0, #fromdate )+1, 0)))
[DateValue]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,#fromdate))
from n as deka cross join n as hecto
)
select
WeekOfMonth = row_number() over (order by datepart(week,DateValue))
, Week = datepart(week,DateValue)
, WeekStart = min(DateValue)
, WeekEnd = max(DateValue)
from dates
group by datepart(week,DateValue)
);
and calling it like so:
set datefirst 1;
select * from dbo.udf_weeks_of_month('20170101');
returns:
+-------------+------+------------+------------+
| WeekOfMonth | Week | WeekStart | WeekEnd |
+-------------+------+------------+------------+
| 1 | 1 | 2017-01-01 | 2017-01-01 |
| 2 | 2 | 2017-01-02 | 2017-01-08 |
| 3 | 3 | 2017-01-09 | 2017-01-15 |
| 4 | 4 | 2017-01-16 | 2017-01-22 |
| 5 | 5 | 2017-01-23 | 2017-01-29 |
| 6 | 6 | 2017-01-30 | 2017-01-31 |
+-------------+------+------------+------------+
and this call:
select * from dbo.udf_weeks_of_month('february 2017');
returns:
+-------------+------+------------+------------+
| WeekOfMonth | Week | WeekStart | WeekEnd |
+-------------+------+------------+------------+
| 1 | 6 | 2017-02-01 | 2017-02-05 |
| 2 | 7 | 2017-02-06 | 2017-02-12 |
| 3 | 8 | 2017-02-13 | 2017-02-19 |
| 4 | 9 | 2017-02-20 | 2017-02-26 |
| 5 | 10 | 2017-02-27 | 2017-02-28 |
+-------------+------+------------+------------+
rextester demo: http://rextester.com/VKPQU7936 (note: rextester reformats the dates)
Something like this?
DECLARE #Dates TABLE (DateId INT IDENTITY, Dt Date);
DECLARE #STart Date = DATEADD(Year, DATEDIFF(Year, 0, GETDATE()),0)
SET NOCOUNT ON;
WHILE #STart <= DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
BEGIN
INSERT INTO #Dates (Dt) VALUES (#STart)
SELECT #Start = DATEADD(DAY, 1, #STart)
END
Updated
SELECT
DateId
, Dt
, DATEADD(WEEK, DATEDIFF(DAY, 0, Dt)/7, 0) AS WeekBeginningMondayOf
, DATEADD(DAY, 6, DATEADD(WEEK, DATEDIFF(DAY, 0, Dt)/7, 0)) AS WeekEndingSundayOf
, DENSE_RANK() OVER(PARTITION BY MONTH(Dt) ORDER BY DATEADD(WEEK, DATEDIFF(DAY, 0, Dt)/7, 0)) AS WeekInMonth
FROM #Dates
It is very smart in such situations to use a numbers / date / tally table. Such a table is very handsome in many situations!
In this answer I show an approach how to create and fill such a table.
Once you have created this table, the query is as simple as:
SELECT n.CalendarDate AS StartOfWeek
,DATEADD(DAY,6,n.CalendarDate) AS EndOfWeek
FROM dbo.RunningNumbers AS n
WHERE n.CalendarDate>={d'2017-01-01'} AND n.CalendarDate<{d'2017-02-01'}
AND n.CalendarWeekDay=1;
hint Such a table can easily be extended with information hardly to compute simply by adding some values into extra columns manually (e.g. holydays, free-of-work days...)
So many variations on this theme. This one is a little shorter than other answers though.
declare #dt date = {fn current_date()};
declare #start_of_year date = datefromparts(year(#dt), 1, 1);
with digits(d) as (
select 0 union all select 1 union all select 2 union all select 3 union all
select 4 union all select 5 union all select 6 union all select 7
), wks as (
select
dateadd(week, d1.d * 8 + d0.d, dateadd(day, 1-datepart(weekday, #start_of_year), #start_of_year)) as week_start,
d1.d * 8 + d0.d as wk
from digits as d0 cross join digits as d1
)
select
case when year(week_start) < year(#dt)
then #start_of_year else week_start end as week_start,
case when year(dateadd(day, 6, week_start)) > year(#dt)
then datefromparts(year(#dt), 12, 31) else dateadd(day, 6, week_start) end as week_end
from wks
where wk between 0 and 53 and year(week_start) = year(#dt)
order by week_start;
I think what you are looking for is here ->someone asked on stackoverflow is similar to what you are looking for it.
This is the final version, hope as per your expectations
I build on the above link hope this is what you are looking for ( Apologies new to stackoverflow, unformatted t-sql below)
DECLARE #sDate DATETIME,
#eDate DATETIME
SET #sDate = '2017-03-01'
SET #eDate = DATEADD(DAY,-1, CAST(Cast(DatePart(YEAR,#sdate) AS varchar(4))
+'-' + Cast((DatePart(MONTH,#sdate)+1) AS varchar(2))+ '-1' AS Date))
SET #sDate = CAST(Cast(DatePart(YEAR,#sdate) AS varchar(4)) +'-'
+ Cast(DatePart(MONTH,#sdate) AS varchar(2))+ '-1' AS Date)
DECLARE #startDayOfWeekOffSet int ;
SET #startDayOfWeekOffSet=
(SELECT DATEPART(DW,#sDate));
DECLARE #DaysToGetFirstSaturday int
SET #DaysToGetFirstSaturday= 7- #startDayOfWeekOffSet
DECLARE #firstEverStartOfWeekDay Date , #firstWeekEndDay Date
SET #firstEverStartOfWeekDay =#sDate;
IF #startDayOfWeekOffSet = 1 -- January
BEGIN
SET #firstEverStartOfWeekDay = #sDate
SET #DaysToGetFirstSaturday = 0
SET #firstWeekEndDay = #sDate END
ELSE BEGIN IF DATEPART(MONTH,#sDate) > DATEPART(MONTH,#firstEverStartOfWeekDay)
AND #startDayOfWeekOffSet = 7 --FirstSundayNewMonth
BEGIN
SET #firstEverStartOfWeekDay =#sDate
SET #firstWeekEndDay = #sDate END ELSE --NotASundayNewMonth
BEGIN
SET #firstWeekEndDay = DATEADD(DAY,#DaysToGetFirstSaturday,#firstEverStartOfWeekDay);
END END
SELECT #firstWeekEndDay AS firstWeekEndDay,
#firstEverStartOfWeekDay AS firstEverStartOfWeekDay,
#DaysToGetFirstSaturday AS DaysToGetFirstSaturday,
#startDayOfWeekOffSet AS startDayOfWeekOffSet ;
WITH cte AS
(SELECT 1 AS WeekNum,
#firstEverStartOfWeekDay StartDate,
#firstWeekEndDay EndDate
UNION ALL SELECT WeekNum + 1, --Case when #scenario = 'NewYear' Then
dateadd(DAY, 1, cte.EndDate) --Else dateadd(ww, 1, cte.StartDate) End as
StartDate,
CASE
WHEN StartDate = EndDate THEN DateAdd(DAY,-1,dateadd(DAY, 8, cte.EndDate))
ELSE dateadd(ww, 1, cte.EndDate)
END AS EndDate
FROM cte
WHERE dateadd(ww, 1, StartDate)<= #eDate )
SELECT WeekNum,
CASE
WHEN DatePart(YEAR, StartDate) < DATEPART(YEAR,#sDate)
THEN CAST(Cast(DatePart(YEAR,#sdate) AS varchar(4)) + '-1-1' AS Date)
WHEN DatePart(MONTH, StartDate) < DATEPART(MONTH,#sDate)
THEN CAST(Cast(DatePart(YEAR,#sdate) AS varchar(4)) + '-'
+ Cast(DatePart(MONTH,#sdate) AS varchar(2)) + '-1' AS Date)
ELSE StartDate
END AS StartDate,
CASE
WHEN DatePart(MONTH, EndDate) > DATEPART(MONTH,#eDate) THEN #eDate
ELSE EndDate
END AS EndDate
FROM cte
select
DateValue
, WeekStart =convert(date,(
case when datepart(week,DateValue) =1
then convert(date, (datename(year,DateValue) +'0101'))
else dateadd(day,##datefirst-datepart(weekday,DateValue)-(##datefirst-1),DateValue)
end) )
, WeekEnd =convert(date,(
case when datepart(week,DateValue) =53
then convert(date, (datename(year,DateValue) +'1231'))
else dateadd(day,(##datefirst)-datepart(weekday,DateValue)+(7-##datefirst),DateValue)
end) )
from dates
rextester demo: http://rextester.com/KYKS44588
test setup:
set datefirst 1;
declare #fromdate date = '20161227', #thrudate date = '20201231';
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, dates as (
select top (datediff(day, #fromdate, #thrudate)+1)
[DateValue]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,#fromdate))
from n as deka cross join n as hecto cross join n as kilo cross join n as [tenK]
order by 1
)
, test as (
select
convert(varchar(10),DateValue,120) as Date
, WeekStart = convert(varchar(10),convert(date,(
case when datepart(week,DateValue) =1
then convert(date, (datename(year,DateValue) +'0101'))
else dateadd(day,##datefirst-datepart(WeekDay,DateValue)-(##datefirst-1),DateValue)
end) ),120)
, WeekEnd = convert(varchar(10),convert(date,(
case when datepart(week,DateValue) =53
then convert(date, (datename(year,DateValue) +'1231'))
else dateadd(day,(##datefirst)-datepart(WeekDay,DateValue)+(7-##datefirst),DateValue)
end) ),120)
, week= datepart(week,DateValue)
from dates
)
select *
, dayname= datename(weekday,date)
, weekstartdayname= datename(weekday,weekstart)
, weekenddayname= datename(weekday,weekend)
from test
where week > 51
or week < 3
order by 1
results:
+------------+------------+------------+------+-----------+------------------+----------------+
| Date | WeekStart | WeekEnd | week | dayname | weekstartdayname | weekenddayname |
+------------+------------+------------+------+-----------+------------------+----------------+
| 2016-12-27 | 2016-12-26 | 2016-12-31 | 53 | Tuesday | Monday | Saturday |
| 2016-12-28 | 2016-12-26 | 2016-12-31 | 53 | Wednesday | Monday | Saturday |
| 2016-12-29 | 2016-12-26 | 2016-12-31 | 53 | Thursday | Monday | Saturday |
| 2016-12-30 | 2016-12-26 | 2016-12-31 | 53 | Friday | Monday | Saturday |
| 2016-12-31 | 2016-12-26 | 2016-12-31 | 53 | Saturday | Monday | Saturday |
| 2017-01-01 | 2017-01-01 | 2017-01-01 | 1 | Sunday | Sunday | Sunday |
| 2017-01-02 | 2017-01-02 | 2017-01-08 | 2 | Monday | Monday | Sunday |
| 2017-01-03 | 2017-01-02 | 2017-01-08 | 2 | Tuesday | Monday | Sunday |
| 2017-01-04 | 2017-01-02 | 2017-01-08 | 2 | Wednesday | Monday | Sunday |
| 2017-01-05 | 2017-01-02 | 2017-01-08 | 2 | Thursday | Monday | Sunday |
| 2017-01-06 | 2017-01-02 | 2017-01-08 | 2 | Friday | Monday | Sunday |
| 2017-01-07 | 2017-01-02 | 2017-01-08 | 2 | Saturday | Monday | Sunday |
| 2017-01-08 | 2017-01-02 | 2017-01-08 | 2 | Sunday | Monday | Sunday |
| 2017-12-18 | 2017-12-18 | 2017-12-24 | 52 | Monday | Monday | Sunday |
| 2017-12-19 | 2017-12-18 | 2017-12-24 | 52 | Tuesday | Monday | Sunday |
| 2017-12-20 | 2017-12-18 | 2017-12-24 | 52 | Wednesday | Monday | Sunday |
| 2017-12-21 | 2017-12-18 | 2017-12-24 | 52 | Thursday | Monday | Sunday |
| 2017-12-22 | 2017-12-18 | 2017-12-24 | 52 | Friday | Monday | Sunday |
| 2017-12-23 | 2017-12-18 | 2017-12-24 | 52 | Saturday | Monday | Sunday |
| 2017-12-24 | 2017-12-18 | 2017-12-24 | 52 | Sunday | Monday | Sunday |
| 2017-12-25 | 2017-12-25 | 2017-12-31 | 53 | Monday | Monday | Sunday |
| 2017-12-26 | 2017-12-25 | 2017-12-31 | 53 | Tuesday | Monday | Sunday |
| 2017-12-27 | 2017-12-25 | 2017-12-31 | 53 | Wednesday | Monday | Sunday |
| 2017-12-28 | 2017-12-25 | 2017-12-31 | 53 | Thursday | Monday | Sunday |
| 2017-12-29 | 2017-12-25 | 2017-12-31 | 53 | Friday | Monday | Sunday |
| 2017-12-30 | 2017-12-25 | 2017-12-31 | 53 | Saturday | Monday | Sunday |
| 2017-12-31 | 2017-12-25 | 2017-12-31 | 53 | Sunday | Monday | Sunday |
| 2018-01-01 | 2018-01-01 | 2018-01-07 | 1 | Monday | Monday | Sunday |
| 2018-01-02 | 2018-01-01 | 2018-01-07 | 1 | Tuesday | Monday | Sunday |
| 2018-01-03 | 2018-01-01 | 2018-01-07 | 1 | Wednesday | Monday | Sunday |
| 2018-01-04 | 2018-01-01 | 2018-01-07 | 1 | Thursday | Monday | Sunday |
| 2018-01-05 | 2018-01-01 | 2018-01-07 | 1 | Friday | Monday | Sunday |
| 2018-01-06 | 2018-01-01 | 2018-01-07 | 1 | Saturday | Monday | Sunday |
| 2018-01-07 | 2018-01-01 | 2018-01-07 | 1 | Sunday | Monday | Sunday |
| 2018-01-08 | 2018-01-08 | 2018-01-14 | 2 | Monday | Monday | Sunday |
| 2018-01-09 | 2018-01-08 | 2018-01-14 | 2 | Tuesday | Monday | Sunday |
| 2018-01-10 | 2018-01-08 | 2018-01-14 | 2 | Wednesday | Monday | Sunday |
| 2018-01-11 | 2018-01-08 | 2018-01-14 | 2 | Thursday | Monday | Sunday |
| 2018-01-12 | 2018-01-08 | 2018-01-14 | 2 | Friday | Monday | Sunday |
| 2018-01-13 | 2018-01-08 | 2018-01-14 | 2 | Saturday | Monday | Sunday |
| 2018-01-14 | 2018-01-08 | 2018-01-14 | 2 | Sunday | Monday | Sunday |
| 2018-12-24 | 2018-12-24 | 2018-12-30 | 52 | Monday | Monday | Sunday |
| 2018-12-25 | 2018-12-24 | 2018-12-30 | 52 | Tuesday | Monday | Sunday |
| 2018-12-26 | 2018-12-24 | 2018-12-30 | 52 | Wednesday | Monday | Sunday |
| 2018-12-27 | 2018-12-24 | 2018-12-30 | 52 | Thursday | Monday | Sunday |
| 2018-12-28 | 2018-12-24 | 2018-12-30 | 52 | Friday | Monday | Sunday |
| 2018-12-29 | 2018-12-24 | 2018-12-30 | 52 | Saturday | Monday | Sunday |
| 2018-12-30 | 2018-12-24 | 2018-12-30 | 52 | Sunday | Monday | Sunday |
| 2018-12-31 | 2018-12-31 | 2018-12-31 | 53 | Monday | Monday | Monday |
| 2019-01-01 | 2019-01-01 | 2019-01-06 | 1 | Tuesday | Tuesday | Sunday |
| 2019-01-02 | 2019-01-01 | 2019-01-06 | 1 | Wednesday | Tuesday | Sunday |
| 2019-01-03 | 2019-01-01 | 2019-01-06 | 1 | Thursday | Tuesday | Sunday |
| 2019-01-04 | 2019-01-01 | 2019-01-06 | 1 | Friday | Tuesday | Sunday |
| 2019-01-05 | 2019-01-01 | 2019-01-06 | 1 | Saturday | Tuesday | Sunday |
| 2019-01-06 | 2019-01-01 | 2019-01-06 | 1 | Sunday | Tuesday | Sunday |
| 2019-01-07 | 2019-01-07 | 2019-01-13 | 2 | Monday | Monday | Sunday |
| 2019-01-08 | 2019-01-07 | 2019-01-13 | 2 | Tuesday | Monday | Sunday |
| 2019-01-09 | 2019-01-07 | 2019-01-13 | 2 | Wednesday | Monday | Sunday |
| 2019-01-10 | 2019-01-07 | 2019-01-13 | 2 | Thursday | Monday | Sunday |
| 2019-01-11 | 2019-01-07 | 2019-01-13 | 2 | Friday | Monday | Sunday |
| 2019-01-12 | 2019-01-07 | 2019-01-13 | 2 | Saturday | Monday | Sunday |
| 2019-01-13 | 2019-01-07 | 2019-01-13 | 2 | Sunday | Monday | Sunday |
| 2019-12-23 | 2019-12-23 | 2019-12-29 | 52 | Monday | Monday | Sunday |
| 2019-12-24 | 2019-12-23 | 2019-12-29 | 52 | Tuesday | Monday | Sunday |
| 2019-12-25 | 2019-12-23 | 2019-12-29 | 52 | Wednesday | Monday | Sunday |
| 2019-12-26 | 2019-12-23 | 2019-12-29 | 52 | Thursday | Monday | Sunday |
| 2019-12-27 | 2019-12-23 | 2019-12-29 | 52 | Friday | Monday | Sunday |
| 2019-12-28 | 2019-12-23 | 2019-12-29 | 52 | Saturday | Monday | Sunday |
| 2019-12-29 | 2019-12-23 | 2019-12-29 | 52 | Sunday | Monday | Sunday |
| 2019-12-30 | 2019-12-30 | 2019-12-31 | 53 | Monday | Monday | Tuesday |
| 2019-12-31 | 2019-12-30 | 2019-12-31 | 53 | Tuesday | Monday | Tuesday |
| 2020-01-01 | 2020-01-01 | 2020-01-05 | 1 | Wednesday | Wednesday | Sunday |
| 2020-01-02 | 2020-01-01 | 2020-01-05 | 1 | Thursday | Wednesday | Sunday |
| 2020-01-03 | 2020-01-01 | 2020-01-05 | 1 | Friday | Wednesday | Sunday |
| 2020-01-04 | 2020-01-01 | 2020-01-05 | 1 | Saturday | Wednesday | Sunday |
| 2020-01-05 | 2020-01-01 | 2020-01-05 | 1 | Sunday | Wednesday | Sunday |
| 2020-01-06 | 2020-01-06 | 2020-01-12 | 2 | Monday | Monday | Sunday |
| 2020-01-07 | 2020-01-06 | 2020-01-12 | 2 | Tuesday | Monday | Sunday |
| 2020-01-08 | 2020-01-06 | 2020-01-12 | 2 | Wednesday | Monday | Sunday |
| 2020-01-09 | 2020-01-06 | 2020-01-12 | 2 | Thursday | Monday | Sunday |
| 2020-01-10 | 2020-01-06 | 2020-01-12 | 2 | Friday | Monday | Sunday |
| 2020-01-11 | 2020-01-06 | 2020-01-12 | 2 | Saturday | Monday | Sunday |
| 2020-01-12 | 2020-01-06 | 2020-01-12 | 2 | Sunday | Monday | Sunday |
| 2020-12-21 | 2020-12-21 | 2020-12-27 | 52 | Monday | Monday | Sunday |
| 2020-12-22 | 2020-12-21 | 2020-12-27 | 52 | Tuesday | Monday | Sunday |
| 2020-12-23 | 2020-12-21 | 2020-12-27 | 52 | Wednesday | Monday | Sunday |
| 2020-12-24 | 2020-12-21 | 2020-12-27 | 52 | Thursday | Monday | Sunday |
| 2020-12-25 | 2020-12-21 | 2020-12-27 | 52 | Friday | Monday | Sunday |
| 2020-12-26 | 2020-12-21 | 2020-12-27 | 52 | Saturday | Monday | Sunday |
| 2020-12-27 | 2020-12-21 | 2020-12-27 | 52 | Sunday | Monday | Sunday |
| 2020-12-28 | 2020-12-28 | 2020-12-31 | 53 | Monday | Monday | Thursday |
| 2020-12-29 | 2020-12-28 | 2020-12-31 | 53 | Tuesday | Monday | Thursday |
| 2020-12-30 | 2020-12-28 | 2020-12-31 | 53 | Wednesday | Monday | Thursday |
| 2020-12-31 | 2020-12-28 | 2020-12-31 | 53 | Thursday | Monday | Thursday |
+------------+------------+------------+------+-----------+------------------+----------------+
Calendar and Numbers table references:
Generate a set or sequence without loops - 1 - Aaron Bertrand
Generate a set or sequence without loops - 3 - Aaron Bertrand
The "Numbers" or "Tally" Table: What it is and how it replaces a loop - Jeff Moden
Creating a Date Table/Dimension in SQL Server 2008 - David Stein
Calendar Tables - Why You Need One - David Stein
Creating a date dimension or calendar table in SQL Server - Aaron Bertrand
TSQL Function to Determine Holidays in SQL Server - Tim Cullen
F_TABLE_DATE - Michael Valentine Jones
First of all please correct me if my title are not specific/clear enough.
I have use the following code to generate the start dates and end dates :
DECLARE #start_date date, #end_date date;
SET #start_date = '2016-07-01';
with dates as
(
select
#start_date AS startDate,
DATEADD(DAY, 6, #start_date) AS endDate
union all
select
DATEADD(DAY, 7, startDate) AS startDate,
DATEADD(DAY, 7, endDate) AS endDate
from
dates
where
startDate < '2017-03-31'
)
select * from dates
Below is part of the output from above query :
+------------+------------+
| startDate | endDate |
+------------+------------+
| 2016-07-01 | 2016-07-07 |
| 2016-07-08 | 2016-07-14 |
| 2016-07-15 | 2016-07-21 |
| 2016-07-22 | 2016-07-28 |
| 2016-07-29 | 2016-08-04 |
+------------+------------+
Now I have another table named sales, which have 3 columns sales_id,sales_date and sales_amount as below :
+----------+------------+--------------+
| sales_ID | sales_date | sales_amount |
+----------+------------+--------------+
| 1 | 2016-07-04 | 10 |
| 2 | 2016-07-06 | 20 |
| 3 | 2016-07-13 | 30 |
| 4 | 2016-07-19 | 15 |
| 5 | 2016-07-21 | 20 |
| 6 | 2016-07-25 | 25 |
| 7 | 2016-07-26 | 40 |
| 8 | 2016-07-29 | 20 |
| 9 | 2016-08-01 | 30 |
| 10 | 2016-08-02 | 30 |
| 11 | 2016-08-03 | 40 |
+----------+------------+--------------+
How can I create the query to show the total sales amount of each week (which is between each startDate and endDate from the first table)? I suppose I will need to use a recursive query with WHERE clause to check if the dates are in between startDate and endDate but I cant find a working example.
Here are my expected result (the startDate and endDate are the records from the first table) :
+------------+------------+--------------+
| startDate | endDate | sales_amount |
+------------+------------+--------------+
| 2016-07-01 | 2016-07-07 | 30 |
| 2016-07-08 | 2016-07-14 | 30 |
| 2016-07-15 | 2016-07-21 | 35 |
| 2016-07-22 | 2016-07-28 | 65 |
| 2016-07-29 | 2016-08-04 | 120 |
+------------+------------+--------------+
Thank you!
Your final Select (after the cte) should be something like this
Select D.*
,Sales_Amount = sum(Sales)
From dates D
Join Sales S on (S.sales_date between D.startDate and D.endDate)
Group By D.startDate,D.endDate
Order By D.startDate
EDIT: You could use a Left Join if you want to see missing dates from
Sales
I have a table like below.
Date | Time | connect |
2013-08-23 00:00:00.000 | 05.26.13 | 1 |
2013-08-23 00:00:00.000 | 05.32.11 | 1 |
2013-08-23 00:00:00.000 | 05.26.13 | 1 |
2013-08-23 00:00:00.000 | 06.02.52 | 1 |
2013-08-23 00:00:00.000 | 06.41.09 | 1 |
2013-08-23 00:00:00.000 | 06.43.12 | 1 |
2013-08-23 00:00:00.000 | 06.52.09 | 1 |
2013-08-23 00:00:00.000 | 06.57.39 | 1 |
2013-10-21 00:00:00.000 | 03.58.35 | 1 |
2013-10-21 00:00:00.000 | 04.02.18 | 1 |
2013-10-21 00:00:00.000 | 04.12.02 | 1 |
2013-10-21 00:00:00.000 | 04.41.36 | 1 |
2013-10-21 00:00:00.000 | 11.12.27 | 1 |
2013-10-22 00:00:00.000 | 11.58.35 | 1 |
I want to get the count of connect that fall in each hour, grouped by date.
Count falling between 1:00 to 1:59, 2:00 to 2:59 and so on. The below is model of the output that I require.
Date | Count(between 4.00.00 to 4.59.59) | Count(between 5.00.00 to 5.59.59) | Count(between 6.00.00 to 6.59.59) |Count(between 11.00.00 to 11.59.59) |
2013-08-23 00:00:00.000 | 0 | 3 | 5 | 0 |
2013-10-21 00:00:00.000 | 3 | 1 | 0 | 1 |
2013-10-22 00:00:00.000 | 0 | 0 | 0 | 1 |
You can just use group by with the date time functions if you don't care about missing 0 row counts, but if you are concerned, use the tally table example Jeff mentions in 2nd page of this forum post: http://www.sqlservercentral.com/Forums/Topic288581-8-1.aspx Both examples in this post, but it note it is by half hour, should be easy to convert to hour.
This is what I want.
by Matt Watson
SELECT [Hourly], COUNT(*) as [Count] FROM (SELECT dateadd(hh, datediff(hh, '20010101', [date_created]), '20010101') as [Hourly] FROM table) idat GROUP BY [Hourly]