Displaying start date of week in SQL - sql

I have a SQL query that to return the number of items per week. I have a query that returns so far this:
Number of Items | Week Number
-------------------------------
100 | 18
80 | 19
120 | 20
And would like to return the following:
Number of Items | Week Beginning
-------------------------------
100 | 1st May 2017
80 | 8th May 2017
120 | 15th May 2017
What I have so far is:
SELECT COUNT(*) AS 'Number of Items', DATEPART(WEEK, Date) FROM table
where DATEPART(Year, Date) = '2017' and DATEPART(MONTH, Date) = 5
group by DATEPART(WEEK, Date)

You are talking about the 1st day of the current week:
example: select FORMAT(dateadd(ww,datediff(ww,0,getdate()),0),'dd MMM yyyy')--if you are using SQL 2012+
answer:
SELECT COUNT(*) AS 'Number of Items', FORMAT(dateadd(ww,datediff(ww,0,date_column),0),'dd MMM yyyy')
FROM table
where DATEPART(Year, Date) = '2017' and DATEPART(MONTH, Date) = 5
group by DATEPART(WEEK, Date)

As you need Monday to be the first day of the week
select DATEPART(WEEK, MyDate),DATEADD(DAY,1,(DATEADD(DAY, 1-DATEPART(WEEKDAY, MyDate), MyDate)))
from (
select '5/3/2017' MyDate
union all select '5/10/2017'
union all select '5/14/2017')A

SELECT DATEADD(DAY, DATEDIFF(DAY, 0, Date) /7*7, 0) AS StartDateOfWeek

check this if it solves
DECLARE #WeekNum INT
, #YearNum char(4);
SELECT #WeekNum = 20
, #YearNum = 2017
-- once you have the #WeekNum and #YearNum set, the following calculates the date range.
SELECT DATEADD(wk, DATEDIFF(wk, 6, '1/1/' + #YearNum) + (#WeekNum-1), 6) AS StartOfWeek;
SELECT DATEADD(wk, DATEDIFF(wk, 5, '1/1/' + #YearNum) + (#WeekNum-1), 5) AS EndOfWeek;
thanks to http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=185440

Related

calculate start date and end date from given quarter SQL

I want to get :
startdate and enddate from a given quarter from between dates
example :
range of dates : 2016-01-01 - 2016-12-31
1 (quarter) - will give me :
start date
2016-01-01
enddate
2016-03-31
2 (quarter) - will give me :
start date
2016-04-01
enddate
2016-06-30
and so on
I made it for only Quarter name and Year, modified it as your need
-- You may need to extend the range of the virtual tally table.
SELECT [QuarterName] = 'Q' + DATENAME(qq,DATEADD(QQ,n,startdate)) + ' ' + CAST(YEAR(DATEADD(QQ,n,startdate)) AS VARCHAR(4))
FROM (SELECT startdate = '01/Jan/2016', enddate = '31/DEC/2016') d
CROSS APPLY (
SELECT TOP(1+DATEDIFF(QQ,startdate,enddate)) n
FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) rc(n)
) x
Check below logic to get your answer.
DECLARE #Year DATE = convert(varchar(20),datepart(YEAR,getdate()))+'-01'+'-01'
DECLARE #Quarter INT = 4
SELECT DATEADD(QUARTER, #Quarter - 1, #Year) ,
DATEADD(DAY, -1, DATEADD(QUARTER, #Quarter, #Year))
SELECT DATEADD(QUARTER, d.q, DATEADD(YEAR, DATEDIFF(YEAR, 0,GETDATE()), 0))
AS FromDate,
DATEADD(QUARTER, d.q + 1, DATEADD(YEAR, DATEDIFF(YEAR, 0, GETDATE()), -1))
AS ToDate
FROM (
SELECT 0 UNION ALL
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 3
) AS d(q)

months between two dates in sql server with starting and end date of each of them in sql server

i want to get months between two dates with their starting and end dates.Suppose if i enter startdate as "2017-04-01" and enddate as "2017-07-31", i want list of months i.e April,May,June,July with their starting and end date respectively.Kindly suggest me how it can be achieved.
One method is a recursive CTE:
with cte as (
select dateadd(day, 1 - day(#startdate), #startdate) as som,
eomonth(#startdate) as eom
union all
select dateadd(month, 1, som), eomonth(dateadd(month, 1, som))
from cte
where dateadd(month, 1, som) < #enddate
)
select *
from cte;
If you want the name of the month, then you can use datename(month, som).
Without recursion, using master.dbo.spt_values as a substitute for a numbers table:
declare #StartDate date = '20170401'
, #EndDate date = '20170731';
;with Months as (
select top (datediff(month,#startdate,#enddate)+1)
[Month] = dateadd(month, row_number() over (order by number) -1, #StartDate)
, MonthEnd = dateadd(day,-1,dateadd(month, row_number() over (order by number), #StartDate))
from master.dbo.spt_values
order by [Month]
)
select * from Months;
rextester demo: http://rextester.com/FXQJ4048
returns:
+------------+------------+
| Month | MonthEnd |
+------------+------------+
| 2017-04-01 | 2017-04-30 |
| 2017-05-01 | 2017-05-31 |
| 2017-06-01 | 2017-06-30 |
| 2017-07-01 | 2017-07-31 |
+------------+------------+
When generating a set or sequence in SQL Server, methods that avoid recursion and loops perform significantly better as the number of values increases.
Reference:
Generate a set or sequence without loops - 1 - Aaron Bertrand
Generate a set or sequence without loops - 2 - Aaron Bertrand
Generate a set or sequence without loops - 3 - Aaron Bertrand
To get the start and end dates of each month within a given range, when the value of the #StartDate parameter is not the first day of the month:
The first option is to truncate the #StartDate parameter to the first of the month, the second option is to adjust the expressions in the common table expression to truncate the values there:
declare #StartDate date = '20170415'
, #EndDate date = '20170715';
/* Option 1: truncate #StartDate to the beginning of the month */
--set #StartDate = dateadd(month, datediff(month, 0, #StartDate), 0);
/* Option 2: Truncate #StartDate to month in the common table expression: */
;with Months as (
select top (datediff(month,#StartDate,#EndDate)+1)
[Month] = dateadd(month
, datediff(month, 0, #StartDate) + row_number() over (order by number) -1
, 0)
, MonthEnd = dateadd(day,-1,dateadd(month
, datediff(month, 0, #StartDate) + row_number() over (order by number)
,0))
from master.dbo.spt_values
order by [Month]
)
select * from Months;
Here you go...
created the schema
create table abc(
date1 date
)
//Inserting data into it
insert into abc values(getdate()),
(DATEADD(Month, -1, getdate())),
(DATEADD(Month, -2, getdate())),
(DATEADD(Month, -3, getdate())),
(DATEADD(Month, -4, getdate()))
and finally the Select Query to fetch the data between Start date and end date:
select (datename(Month, date1)+' '+convert(varchar(2), date1, 103)) as [Date] from abc
where convert(varchar(10), date1, 120) between '2017-05-02' and '2017-07-02'
Another approach to fetch the between two dates data:
select (datename(Month, date1)+' '+convert(varchar(2), date1, 103)) as [Date] from abc
where date1 >= (DATEADD(Month, -3, getdate())) AND date1 <=getdate();
And the returned result is:
this is the Fiddle where you can test this query -> SQL FIDDLE
Simple and easy...good luck bro :)
Try this:
DECLARE #Start DATE ='2017-04-01',
#End DATE ='2017-07-31'
SELECT *, Datename(mm, date),
Dateadd(mm, Datediff(mm, 0, date), 0) AS FirstDateOfMonth,
Dateadd (dd, -1, Dateadd(mm, Datediff(mm, 0, date) + 1, 0)) as
LastDateOfMonth
FROM dbo.TableName
WHERE Cast(date AS DATE) BETWEEN #Start AND #End
If this is not just a one-off report, then I would create a calendar table, and use that to "group by". This will also let you do many other date related calculations.
You can find one at simple calendar or one here at Stackoverflow
Then your code could look like this:
SELECT top 10000 * FROM dbo.calendar DD
WHERE DD.TimeStampFrom>='2017-04-01' AND DD.TimeStampFrom <='2017-07-31'
AND DAY(DD.TimeStampFrom)=1
I created a stored procedure for that, may be you can convert that into user defined Function.
Posting that code below,
create procedure ListMonths
#date1 date,#date2 date
as
begin
create Table #tempTable
(mnth varchar(10))
while #date1<#date2
begin
insert into #tempTable
select DATENAME(month,#date1)
set #date1 = DATEADD(MONTH,1,#date1)
end
select * from #tempTable;
drop table #tempTable;
end
To execute the stored procedure:
exec ListMonths '2017-04-01','2018-01-31'
output
+------------+
| mnth |
+------------+
| April |
| May |
| June |
| July |
| August |
| September |
| October |
| November |
| December |
| January |
+------------+
result

need to calculate year,month and day for closing date

I have a table called dates,
Opendate | Closedate
------------+---------------
2015-07-09 | 2016-08-10
I am expecting the output like,
opendate | closedate | diff
------------+---------------+----------------------
2015-07-09 | 2016-08-10 | 1year 1month 1day
2015-07-09 | 2016-03-01 | 8 months 20 days
2015-07-09 | 2015-07-11 | 2 days
But when I run this query:
SELECT opendate,
closedate,
Datediff(year, opendate, closedate) AS years,
Datediff(month, opendate, closedate) AS months,
Datediff(day, opendate, closedate) AS days
FROM dates
It is giving me an output like,
opendate | closedate | years | months | days
------------+---------------+-------+--------+---------
2015-07-09 | 2016-08-10 | 1 | 13 | 397
How can we calculate 1 year 1 month and 1 day
You can use Stacked CTE to find one by one the next year, month and date.
Explanation
Query Below first finds out the DATEDIFF Years of opendate and closedate and checks if the resulting date is greater than closedate. if it is, the actual year difference is DATEDIFF of Y -1. use this new date and fetch the DATEDIFF of months using the same logic and then get the difference in days.
Online Example
Query
WITH D(Opendate,Closedate)AS
(
SELECT CAST('2015-07-09' AS DATE),CAST('2016-08-10' AS DATE)
UNION ALL
SELECT CAST('2015-07-09' AS DATE),CAST('2016-03-01' AS DATE)
UNION ALL
SELECT CAST('2015-07-09' AS DATE),CAST('2015-07-11' AS DATE)
),Y AS
(
SELECT Opendate,Closedate,
CASE
WHEN DATEADD(YEAR,DATEDIFF(YEAR,Opendate,Closedate),Opendate) > Closedate
THEN DATEDIFF(YEAR,Opendate,Closedate) - 1
ELSE DATEDIFF(YEAR,Opendate,Closedate)
END Years
FROM D
), YDate as
(
SELECT Opendate,Closedate,Years,DATEADD(YEAR,Years,Opendate) as Newopendate
FROM Y
),M AS
(
SELECT Opendate,Closedate,Years,Newopendate,
CASE WHEN DATEADD(MONTH,DATEDIFF(MONTH,Newopendate,Closedate),Newopendate) > Closedate
THEN DATEDIFF(MONTH,Newopendate,Closedate) - 1
ELSE DATEDIFF(MONTH,Newopendate,Closedate)
END Months
FROM YDate
)
SELECT Opendate,Closedate,Years,Months,DATEDIFF(Day,DATEADD(MONTH,Months,Newopendate),Closedate) as days
FROM M
Result
Opendate Closedate Years Months days
09-07-2015 00:00 10-08-2016 00:00 1 1 1
09-07-2015 00:00 01-03-2016 00:00 0 7 21
09-07-2015 00:00 11-07-2015 00:00 0 0 2
SELECT opendate,
closedate,
( ( Datediff(year, opendate, closedate) + 'years' )+
(( Datediff(month, opendate, closedate) -
12 * Datediff(year, opendate, closedate)) + 'months') +
( Datediff(day, opendate, closedate) -
( Datediff(year, opendate, closedate) * 365 -
(Datediff(month, opendate, closedate) * 12) )) + 'days'
FROM dates
The logic is you concatenate the years and then deduct the no of months of a year. Similarly deduct for days as well
Create one function as Below
CREATE FUNCTION dbo.GetYearMonthDays
(
#FromDate DATETIME
)
RETURNS NVARCHAR(100)
AS
BEGIN
DECLARE #date datetime, #tmpdate datetime, #years int, #months int, #days int
SELECT #date =#FromDate
SELECT #tmpdate = #date
SELECT #years = DATEDIFF(yy, #tmpdate, GETDATE()) - CASE WHEN (MONTH(#date) > MONTH(GETDATE())) OR (MONTH(#date) = MONTH(GETDATE()) AND DAY(#date) > DAY(GETDATE())) THEN 1 ELSE 0 END
SELECT #tmpdate = DATEADD(yy, #years, #tmpdate)
SELECT #months = DATEDIFF(m, #tmpdate, GETDATE()) - CASE WHEN DAY(#date) > DAY(GETDATE()) THEN 1 ELSE 0 END
SELECT #tmpdate = DATEADD(m, #months, #tmpdate)
SELECT #days = DATEDIFF(d, #tmpdate, GETDATE())
RETURN CONVERT(varchar(10), #years) +' Years ' + CONVERT(varchar(10), #months) + ' Month ' + CONVERT(varchar(10), #days) + ' Days'
END
GO
And use is as below
SELECT opendate,
closedate,dbo.GetYearMonthDays(closedate)
FROM dates
This will give you what you wants.

Find first date of previous week in SQL Server

I have some dates and week numbers and first day of week is 5 (Friday) in SQL Server. Now I want to calculate previous week and week start date from this below query.
DECLARE #LocationID tinyint = 1,
#FromDate date = '2016-05-20',
#ToDate date = '2016-05-29';
--Step1: ==================================================================
--SET first day of the week of the year
DECLARE #CurrentDayOfWeek INT
SET DATEFIRST 1 -- normalize current dkoray of week to Monday
SET #CurrentDayOfWeek = DATEPART(DW, DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0))
SET DATEFIRST #CurrentDayOfWeek -- first day of week is now 5 (Friday)
--SELECT #CurrentDayOfWeek
-----Get Weekend number--------------
DECLARE #WeekStart int, #WeekEnd int
SET #WeekStart=(SELECT { fn WEEK( #FromDate) })
SET #WeekEnd=(SELECT { fn WEEK( #ToDate) })
;WITH AllDate AS
(
SELECT #FromDate as TheDate
UNION ALL
SELECT DATEADD(DAY, 1, TheDate)
FROM AllDate
WHERE DATEADD(DAY, 1, TheDate) <= #ToDate
),
AllDateDetail AS
(
SELECT TheDate,
DATEPART(WEEK, TheDate) AS WeekNumber,
YEAR(TheDate) AS [Year],
UPPER(CONVERT(NVARCHAR(3),DATENAME(WEEKDAY, TheDate))) AS [DayName]
FROM AllDate
)
SELECT
*
, CONVERT(DATE,DATEADD(WK, DATEDIFF(WK, 0, TheDate), 0)) AS LastWeekStart
, { fn WEEK( CONVERT(DATE,DATEADD(WK, DATEDIFF(WK, 0, TheDate) - 1, 0))) } AS WeekNumber
FROM AllDateDetail
--Select dateadd(wk, datediff(wk, 0, getdate()) - 1, 0) as LastWeekStart
--Select dateadd(wk, datediff(wk, 0, getdate()), 0) as ThisWeekStart
--Select dateadd(wk, datediff(wk, 0, getdate()) + 1, 0) as NextWeekStart
The current result of this query:
Expected result:
TheDate WeekNumber [Year] [DayName] LastWeekStart LastWeekNumber
20-05-2016 21 2016 FRI 13-05-2016 20
21-05-2016 21 2016 SAT 13-05-2016 20
22-05-2016 21 2016 SUN 13-05-2016 20
23-05-2016 21 2016 MON 13-05-2016 20
24-05-2016 21 2016 TUE 13-05-2016 20
25-05-2016 21 2016 WED 13-05-2016 20
26-05-2016 21 2016 THU 13-05-2016 20
27-05-2016 22 2016 FRI 20-05-2016 21
28-05-2016 22 2016 SAT 20-05-2016 21
29-05-2016 22 2016 SUN 20-05-2016 21
Can you help me? Thanks
Here's some handy ways of calculating First/Last day of This/Last week respecting DATEFIRST that I blogged a couple of weeks ago.
SET DATEFIRST 5 --Friday
-- Start/End of Weeks respecting DATEFIRST
SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, GETDATE()), GETDATE()) 'First Day of Current Week (DATEFIRST)';
SELECT DATEADD(DAY, 7-DATEPART(WEEKDAY, GETDATE()), GETDATE()) 'Last Day of Current Week (DATEFIRST)';
SELECT DATEADD(DAY, -6-DATEPART(WEEKDAY, GETDATE()), GETDATE()) 'First Day of Last Week (DATEFIRST)';
SELECT DATEADD(DAY, 0-DATEPART(WEEKDAY, GETDATE()), GETDATE()) 'Last Day of Last Week (DATEFIRST)';
(Gratuitous blog promo https://www.rednotebluenote.com/2016/04/first-day-of-the-week-and-datefirst/ )

Query not displaying the week value as 0

SELECT datediff(week, dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, EntryDate), 0)), 0), EntryDate - 1) + 1 as week,
count(UserID) as balance
FROM table_points
where right(convert(varchar, EntryDate, 106), 8)='Mar 2015'
GROUP BY datediff(week, dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, EntryDate), 0)), 0), EntryDate - 1) + 1
When i execute this query i get result for 4th and 5th week values but not for others week. Like
week balance
4 80
5 100
In first 3 weeeks there is no values in database so it will not showing the values . Can any one bring 0 value for 1st , 2nd and 3rd week.
I want result as
week balance
1 0
2 0
3 0
4 80
5 100
can any one help me out.
Create a calendar/date table, including all possible dates/weeks, and from there left join the table_points table.
If no data is present in table_points, it will return 0 for those weeks.
If no dates are present in a table, it's impossible to select these and get a zero.
Example:
SELECT d.week, count(t.UserID)
FROM dates d left join table_points t on
d.date = t.EntryDate
where right(convert(varchar, d.date, 106), 8)='Mar 2015'
group by d.week
A date table can be very useful for many applications and could be filled like:
date week year month WeekOfMonth DayOfWeek Day Month
2015-03-01 18 2015 3 1 5 Friday March
2015-03-02 18 2015 3 1 6 Friday March
2015-03-03 18 2015 3 1 7 Sunday March
2015-03-04 19 2015 3 2 1 Monday March
This works like PSVSupporter's solution but uses a CTE to get a date list instead of using another table:
;WITH Dates AS (
SELECT
[Date] = CONVERT(DATETIME,'03/01/2015')
UNION ALL SELECT
[Date] = DATEADD(DAY, 1, [Date])
FROM
Dates
WHERE
Date < '03/31/2015'
)
SELECT
datediff(week, dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, ds.Date), 0)), 0), ds.Date - 1) + 1 as week,
count(tp.UserID) as balance
FROM Dates ds
left join table_points tp on tp.EntryDate = ds.Date
WHERE right(convert(varchar, ds.Date, 106), 8)='Mar 2015'
GROUP BY datediff(week, dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, ds.Date), 0)), 0), ds.Date - 1) + 1
I took CTE from https://stackoverflow.com/a/7824893/3309109