Number of days in quarter, SQL Server - sql

I want to calculate the number of days per-quarter if start date and finish dates are given.
for example, one table has two columns, start date and finish date.
start date = 1st september and finish is 14th november.
I want to calculate the number of days present in between these two days that are present in each quarter
Q3 - 30 days
Q4 - 45 days (for this scenario)
Regards.

declare #StartDate date='2012-09-01';
declare #EndDate date='2012-11-14';
select CEILING(month(dateadd(q,datediff(q,0,dateadd(dd,number ,#StartDate)),0))/3.0) as QuarterNo,
COUNT(*) as 'number of days'
from master..spt_values
where type='p'
and dateadd(dd,number ,#StartDate)<=#EndDate
group by dateadd(q,datediff(q,0,dateadd(dd,number ,#StartDate)),0)
SQL fiddle demo

You can use a recursive query to get this. This generates the list of dates between your start and end date and then gets the count of days per quarter:
;with cte (start, enddate) as
(
select startdate, enddate
from yourtable
union all
select dateadd(dd, 1, start), enddate
from cte
where dateadd(dd, 1, start) <= enddate
)
select datepart(q, start) Quarter, count(datepart(q, start)) NoDays
from cte
group by datepart(q, start)
See SQL Fiddle with Demo

Related

How to loop through each value from CTE

I am working only on queries for now and not TSQL. So i want to fetch my results thru query.
I want to display first monday of every month. I have comeup with a query to find the dates of every month in tht year thru CTE. (So my CTE gives 12 dates).
Now , i want to check each date and get the nearest monday. That would be my first monday of that month.
I am unable to go thru each date in my query.
How can i work on this result set?
Thanks
with
Wk_num
as
(select 1 as n
union all
select n=n+1
from wk_num
where n <12)
select dateadd(month,n,getdate()) from wk_num
A relatively simple method use modulo arithmetic:
with cte as (
select convert(date, '2019-01-01') as dte
union all
select dateadd(month, 1, dte)
from cte
where dateadd(month, 1, dte) < '2020-01-01'
)
select dte,
dateadd(day, (9 - datepart(weekday, dte)) % 7, dte) as first_monday
from cte;
This assumes that the weekday numbers starts with 1 on Sunday.
Here is the code to actually get the first day of each month and the first Monday of each month (This doesn't use any complex functions just simple date functions):
with Wk_num as
(select 1 as n
union all
select n=n+1 from wk_num where n <12)
select dateadd(month,n,datefromparts(year(getdate()),month(getdate()),1)) as FirstDay,
dateadd(day,iif(9-datepart(dw,dateadd(month,n,datefromparts(year(getdate()),month(getdate()),1)))>7,2-datepart(dw,dateadd(month,n,datefromparts(year(getdate()),month(getdate()),1))),9-datepart(dw,dateadd(month,n,datefromparts(year(getdate()),month(getdate()),1)))),dateadd(month,n,datefromparts(year(getdate()),month(getdate()),1))) as FirstMonday
from wk_num

Get week number from a list of dates in SQL

I'm trying to get listed the corresponding week number from the dates that result from this query.
select Date,Time,EndDate,EndTime
FROM Test
WHERE (StartDate >= '01.01.2019')
ORDER BY StartDate
Basically, I want adding to the end column the week number from this query.
I can't edit the database in anyway, I just want to extract the week number from the dates and have it as a column at the end of my results.
Sample data below:
Just use datepart function:
select datepart(week, Date), Date,Time,EndDate,EndTime
FROM Test
WHERE (StartDate >= '01.01.2019')
ORDER BY StartDate
use datepart(wk,date):-
select Date,Time,EndDate,EndTime,datepart(wk,date)as week
FROM Test
WHERE (StartDate >= '01.01.2019')
ORDER BY StartDate
In UK ISO week is used: the first year's week is the one including 4th of Jan.
So:
set datefirst 1 --this sets Monday as first day of the week
set dateformat dmy -- nosrmal date format
select Date,Time,EndDate,EndTime,datepart(iso_week,date)as week
FROM Test
WHERE (StartDate >= '01.01.2019')
ORDER BY StartDate
Remember that first days of Jan may be 52nd or 53rd week of previous year and also last day of December may belong to first week of new year.
the check to see the week number and postponed to the yeear it belongs to is the following:
week_and_year = case when datepart(iso_week,date)>=52 and month(date)=1
then concat(year(date)-1,datepart(iso_week,date))
when datepart(iso_week,date)=1 and month(date)=12
then concat(year(date)+1,datepart(iso_week,date))
else concat(year(date),datepart(iso_week,date))
end
SELECT DATEPART(WEEK,GETDATE()-14)
SELECT DATEPART(WEEK,GETDATE()-7)
SELECT DATEPART(WEEK,GETDATE())
SELECT DATEPART(WEEK,GETDATE()+7)
SELECT DATEPART(WEEK,GETDATE()+14)
If you use Vertica, try this
date_part('ISODOW', date)
'ISODOW' - The ISO day of the week, an integer between 1 and 7 where Monday is 1.
I usually use the ROW_NUMBER() function to accomplish this:
select
Date,
Time,
EndDate,
EndTime,
ROW_NUMBER() over (partition by year(EndDate), datepart(weekday, EndDate) order by EndDate) as WeekNumInYear
FROM Test
WHERE
(StartDate >= '01.01.2019')
ORDER BY
StartDate

52weeks rolling with running week data

Can someone suggest me how do we consider week to start on Sunday and end on Saturday, while numbering them backwards in a 52 week rolling report like week1, week2.. week52
I want to count my current week as Week1 starting on Sunday, so even if its partial week its still week1 and last week Sunday-Saturday is week2 and so on until 52nd week last year (that would roughly be in September counting backwards). I need this as I am working on a daily report that will look for sales for current week and past 51 (full) weeks. My report should also return any week without sales '0' without skipping it.
Here is a way. Note I created the recursive CTE to populate some dates. You won't have to do this step, and real only need the YourWeekOrder = ... part.
declare #startDate date = dateadd(year,-1,getdate())
declare #endDate date = getdate()
;with cte as(
select #startDate as TheDate
union all
select dateadd(day,1,TheDate)
from cte
where TheDate < #endDate)
select
TheDate
,TheWeekOfYear = datepart(week,TheDate)
,YourWeekOrder = dense_rank() over (order by cast(datepart(year,TheDate) as char(4)) + case when len(datepart(week,TheDate)) = 1 then '0' + cast(datepart(week,TheDate) as char(2)) else cast(datepart(week,TheDate) as char(2)) end desc)
from cte
order by
TheDate
option(maxrecursion 0)
SEE IT IN ACTION HERE

SQL Server : is there a way for me to get weeks per month using Month and Year?

I'm not really good when it comes to database...
I'm wondering if it is possible to get the weeks of a certain month and year..
For example: 1 (January) = month and 2016 = year
Desired result will be:
week 1
week 2
week 3
week 4
week 5
This is what I have tried so far...
declare #date datetime = '01/01/2016'
select datepart(day, datediff(day, 0, #date) / 7 * 7) / 7 + 1
This only returns the total of the weeks which is 5.
declare #MonthStart datetime
-- Find first day of current month
set #MonthStart = dateadd(mm,datediff(mm,0,getdate()),0)
select
Week,
WeekStart = dateadd(dd,(Week-1)*7,#MonthStart)
from
( -- Week numbers
select Week = 1 union all select 2 union all
select 3 union all select 4 union all select 5
) a
where
-- Necessary to limit to 4 weeks for Feb in non-leap year
datepart(mm,dateadd(dd,(Week-1)*7,#MonthStart)) =
datepart(mm,#MonthStart)
Got the answer in the link: http://www.sqlservercentral.com/Forums/Topic1328013-391-1.aspx
Here is one way to approach this:
A month has a minimum of 29 or more days, and a max of 31 or less. Meaning there are almost always 5 weeks a month, with the exception of a non-leap year's feburary, and in those cases, 4 weeks a month.
You can refer to this to find out which years are "leap".
Check for leap year
Hope this helps!
The following code will allow you to select a start and end date, and output one row per week, with numbered weeks, between those dates:
declare #start date = '1/1/2016'
declare #end date = '5/1/2016'
;with cte as (select #start date
, datename(month, #start) as month
union all
select dateadd(dd, 7, date)
, datename(month, dateadd(dd, 7, date))
from CTE
where date <= #end
)
select *, 'week '
+ cast(row_number() over (partition by month order by date) as varchar(1))
from CTE
order by date

How can I count and group by between two date?

For example,
the start date = '20100530' and
the end date = '20100602'
How can I write a SQL to display the below result?
month: may, 2 days
month: June, 2 days
Use a recursive CTE to generate all of the dates between the start and end, and then do a simple group and count (caution, not tested, but should be close if not exactly right):
with dates (the_date) as (
select #start_date
UNION ALL
select dateadd(dd, 1, the_date) from dates where the_date <= #end_date
)
select
datepart(mm, the_date) month,
count(*) num_days
from
dates
group by
datepart(mm, the_date)
TBH, you really need to provide more schema and information about the source data. However, given what little we know, you should be able to write:
Select DateName('month', [Date]) As Month
, Cast(DateDiff(d, #StartDate, #EndDate) As varchar(10) - 1) + ' days'
From Table
Where [Date] Between #StartDate And #EndDate
What we'd need to know to refine our solutions is exactly how 2 days is supposed to be calculated. Is it the days between the start and end date? Is it the day of the second parameter?