adding 7 days to a date until end of month sql server - sql

I want to find the first day of the month add 7 days and keep on adding 7 days not going over available days left in that month.
Example
July 1 – 7 --> 7 Days
July 8 – 14 --> 7 Days
July 15 – 21 --> 7 Days
July 22 – 28 --> 7 Days
July 29 - 31 --> 3 Days`

This works for me. Could be generalized to not have to start on the first day of the month and there is probably a more compact way to do this, but this gets the job done.
declare #month varchar(2) = '10',
#year varchar(4) = '2015',
#fullWeekCount int;
declare #firstOfTheMonth datetime = #year + '-' + #month + '-1';
declare #daysInMonth int = datediff(day, #firstOfTheMonth, dateadd(month, 1, #firstOfTheMonth))
select #fullWeekCount = (#daysInMonth / 6)
declare #i int = 1,
#startDate datetime = #firstOfTheMonth,
#endDate datetime;
declare #dates table (StartDay datetime, EndDay datetime);
while (#i <= #fullWeekCount)
begin
if (#i = #fullWeekCount)
set #endDate = #year + '-' + #month + '-' + cast(#daysInMonth as varchar(2));
else
set #endDate = dateadd(day, 6, #startDate)
insert into #dates (StartDay, EndDay)
values (#startDate, #endDate)
set #startDate = dateadd(day, 1, #endDate)
set #i = #i + 1;
end
select * from #dates d

Related

How Calculate Expire Date in SQL Query

I have this query for expiry date calculation and its work fine but result show in - eg:-9 year 4 month and 5 day.
I want to show that in normal way like "Expire in 9 years 4 months and 5 day":
DECLARE #TempDate Datetime ,
#ExpiryDate Datetime,
#year int,
#month int,
#day int
SET #ExpiryDate = (SELECT TOP (1) [ExpiryDate] FROM [dbo].[Purchases] WHERE [ProductId] = 1)
SELECT #TempDate = #ExpiryDate
SELECT
#year = DATEDIFF(YEAR, #TempDate, GETDATE()) -
CASE
WHEN (MONTH(#ExpiryDate) > MONTH(GETDATE())) OR
(MONTH(#ExpiryDate) = MONTH(GETDATE()) AND DAY(#ExpiryDate) > DAY(GETDATE()))
THEN 1 ELSE 0
END
SELECT #TempDate = DATEADD(YEAR, #year, #TempDate)
SELECT #month = DATEDIFF(MONTH, #TempDate, GETDATE()) -
CASE
WHEN DAY(#ExpiryDate) > DAY(GETDATE())
THEN 1 ELSE 0
END
SELECT #TempDate = DATEADD(MONTH, #month, #TempDate)
SELECT #day = DATEDIFF(DAY, #TempDate, GETDATE())
SELECT #year AS Years, #month AS Months, #day AS [Days]
If I understand your question correctly, the calculation is working as you expect but you want the Years value to be returned as a positive rather than negative number. If this is the case, you should change the final SELECT to:
SELECT (#year * -1) AS Years, #month AS Months, #day AS [Days];
Alternatively if you want to return the output as a string (i.e. Expire in 9 years 4 months and 5 day), change the final SELECT to:
SELECT 'Expire in ' + CAST((#year * -1) AS VARCHAR(2)) + ' years '
+ CAST(#month AS VARCHAR(2)) + ' months and '
+ CAST(#day AS VARCHAR(2)) + ' day';
Casting as VARCHAR(2) assumes that you expect no more than 99 years, but you may want to increase that number.

Show dates against each un-pivoted column?

I have written this query to convert columns into the rows.
select [ProjectName], EachDay, Hours
from [dbo].[TimeSheet_Child]
unpivot
(
Hours
for EachDay in ([Mon], [Tue], [Wed])
) u
but instead of EachDay I need dates that comes between the start and end of the week e.g.
Currently:
ProjectName EachDay Hours
A Mon 2
B Tue 8
C Wed 1
Should be
ProjectName EachDay Hours
A 15Dec2019 2
B 16Dec2019 8
C 17Dec2019 1
To pick dates between week start and end I have written this.
Declare #Year int
,#Week int
,#YearText varchar(4)
set #Year = 2019
set #Week = 51
set #YearText = #Year
Declare #Increment int
Set #Increment= 1
declare #date datetime
Set #date= dateadd(day
,#Increment - datepart(dw, #YearText + '-01-01')
+ (#Week-1) * 7
,#YearText + '-01-01')
print #date
While (#Increment < 8)
Begin
print dateadd(day
,#Increment - datepart(dw, #YearText + '-01-01')
+ (#Week-1) * 7
,#YearText + '-01-01')
Set #Increment= #Increment + 1
End

Find Quarter Months Based on Payroll Cycle

This would be in the "where" clause...how do I find quarters based on a payroll cycle? Our payroll cycle starts on the 25th of the quarter month and ends on the 10th of the quarter month. For example...
The 2nd quarter starts on 4/25/2016 and ends on 7/10/2016.
Ok it's kind of hard to understand completely what you are doing but here is something that should work. You can edit the dates to fit what you want but I made it based off what you stated.
--This is just test data... you can use your own table
IF OBJECT_ID('tempdb..#payroll') IS NOT NULL DROP TABLE #payroll
CREATE TABLE #payroll (dates date)
INSERT INTO #payroll (dates) VALUES
('1/1/2016'),
('1/16/2016'),
('2/4/2016'),
('3/3/2016'),
('3/19/2016'),
('4/18/2016'),
('5/6/2016'),
('6/4/2016'),
('6/29/2016'),
('7/4/2016'),
('7/31/2016'),
('8/9/2016'),
('9/1/2016'),
('10/3/2016'),
('10/19/0216'),
('11/4/2016'),
('11/21/2016'),
('12/2/2016'),
('1/1/2016'),
('1/8/2017'),
('1/21/2017')
--variable for what ever quarter you want to limit on. 1-4
declare #Quarter int
set #Quarter = 4
--Year that you are focused on. If left to NULL it uses the current year
declare #Year int
set #Year = NULL
IF #Year IS NULL
BEGIN
SET #Year = Year(GETDATE())
END
--Date parameters that we will use to filter
declare #startDate date = null
declare #endDate date = null
--logic to set your quarters
set #startDate = case
when #Quarter = 1 then '1/25/' + CAST(#Year as varchar(4))
when #Quarter = 2 then '4/25/' + CAST(#Year as varchar(4))
when #Quarter = 3 then '7/25/' + CAST(#Year as varchar(4))
when #Quarter = 4 then '9/25/' + CAST(#Year as varchar(4))
end
set #endDate = case
when #Quarter = 1 then '4/10/' + CAST(#Year as varchar(4))
when #Quarter = 2 then '7/10/' + CAST(#Year as varchar(4))
when #Quarter = 3 then '9/10/' + CAST(#Year as varchar(4))
when #Quarter = 4 then '1/10/' + CAST((#Year + 1)as varchar(4))
end
--run it to test results
select *
from #payroll
where dates between #startDate and #endDate

Iterate by increment of parameter

I have Sql query as below example.
Select
number,age
from
tbldetails
where
month = #Month and year = #Year
union
Select
number,age
from
tblcontacts
where
month = #Month and year = #Year
Now I want to get details of above query for past 12 months of #Month and #Year and then do average on age.
Example #Month = Dec and #Year = 2015
I want to get age for Jan 2015 to Dec 2015 and then do average .
I want to use this in ssrs report.
Hoping to get some help :)
To filter for the desired date range, I would combine the year and month into one string column and then use that to compare to your converted parameters (minus one year).
WHERE CAST(YEAR AS VARCHAR(4) + RIGHT('00' + CAST(MONTH AS VARCHAR(2)), 2)
>= CAST((#YEAR - 1) AS VARCHAR(4) + RIGHT('00' + CAST(#MONTH AS VARCHAR(2)), 2)
Declare #Year int;
Set #Year = '2016'
Declare #Month varchar(10);
Set #Month = '11'
Declare #Date varchar(10);
Set #Date = Cast(#Month as varchar(2))+'-'+'01'+'-'+Cast(#year as varchar(4))
Declare #StartDate varchar(19);
Set #StartDate = Convert(varchar(19),DateAdd(m,-12,#Date),103) -- 103 dd/mm/yy
Declare #EndDate varchar(20);
Set #EndDate = Convert(varchar(20),DateAdd(m,12,#StartDate),103)
Select
Sum( StCount) as TotalStudents
(
Select Count(Rollnbr) as StCount,..
Where Date between #StartDate and #EndDate
union
Select Count(Rollnbr) as StCount,..
Where Date between #StartDate and #EndDate
)Sql1

SQL: How to produce next date given month and day

In my table I have a Month(tinyint) and a Day(tinyint) field. I would like to have a function that takes this month and day and produces a datetime for the next date(including year) given this month and day.
So if I had Month = 9, Day = 7 it would produce 9/7/2009.
If I had Month 1, Day 1 it would produce 1/1/2010.
something like this would work. It's variation on your method, but it doesn't use the MM/DD/YYYY literal format, and it won't blowup against bad input (for better or for worse).
declare #month tinyint
declare #day tinyint
set #month = 9
set #day = 1
declare #date datetime
-- this could be inlined if desired
set #date = convert(char(4),year(getdate()))+'0101'
set #date = dateadd(month,#month-1,#date)
set #date = dateadd(day,#day-1,#date)
if #date <= getdate()-1
set #date = dateadd(year,1,#date)
select #date
Alternatively, to create a string in YYYYMMDD format:
set #date =
right('0000'+convert(char(4),year(getdate())),4)
+ right('00'+convert(char(2),#month),2)
+ right('00'+convert(char(2),#day),2)
Another method, which avoids literals all together:
declare #month tinyint
declare #day tinyint
set #month = 6
set #day = 24
declare #date datetime
declare #today datetime
-- get todays date, stripping out the hours and minutes
-- and save the value for later
set #date = floor(convert(float,getdate()))
set #today = #date
-- add the appropriate number of months and days
set #date = dateadd(month,#month-month(#date),#date)
set #date = dateadd(day,#day-day(#date),#date)
-- increment year by 1 if necessary
if #date < #today set #date = dateadd(year,1,#date)
select #date
Here is my sql example so far. I don't really like it though...
DECLARE #month tinyint,
#day tinyint,
#date datetime
SET #month = 1
SET #day = 1
-- SET DATE TO DATE WITH CURRENT YEAR
SET #date = CONVERT(datetime, CONVERT(varchar,#month) + '/' + CONVERT(varchar,#day) + '/' + CONVERT(varchar,YEAR(GETDATE())))
-- IF DATE IS BEFORE TODAY, ADD ANOTHER YEAR
IF (DATEDIFF(DAY, GETDATE(), #date) < 0)
BEGIN
SET #date = DATEADD(YEAR, 1, #date)
END
SELECT #date
Here's a solution with PostgreSQL
your_date_calculated = Year * 10000 + Month * 100 + Day
gives you a date like 20090623.
select cast( cast( your_date_calculated as varchar ) as date ) + 1
Here's my version. The core of it is just two lines, using the DATEADD function, and it doesn't require any conversion to/from strings, floats or anything else:
DECLARE #Month TINYINT
DECLARE #Day TINYINT
SET #Month = 9
SET #Day = 7
DECLARE #Result DATETIME
SET #Result =
DATEADD(month, ((YEAR(GETDATE()) - 1900) * 12) + #Month - 1, #Day - 1)
IF (#Result < GETDATE())
SET #Result = DATEADD(year, 1, #Result)
SELECT #Result