How to get NextDayofWeek if you pass the date? - sql

Here's what I am trying to do. I will change the following code into SP which takes two parameter #startdate, and #transactionDate, and it will return the NextTransactiondate. The logic is #startdate determine which day of the week it is. The #NexttransactionDate should be equal to the day following the transactiondate. so in this example, the startday is Wednesday so the next transaction date should be - 2011-05-04'. In the code below, it is always computing to friday, but it should be dynamically compute based on the day. Any help is appreciated?
declare #TransactionDate datetime
declare #startDate datetime
declare #startDay int
declare #NextTransactionDate datetime
--Monday
set #TransactionDate = '2011-05-02'
--Wednesday
set #startDate = '2011-04-27'
set #startDay = datepart(dw,#startDate)
set #NextTransactionDate= DATEADD(DAY,(CASE DATEPART(DW,#TransactionDate)
WHEN 7 THEN 6
WHEN 6 THEN 7
ELSE 6 - DATEPART(DW,#TransactionDate)
END),#TransactionDate);
print #NextTransactionDate

The following works for me:
declare #TransactionDate DATETIME
DECLARE #TransactionDay tinyint
declare #startDate datetime
declare #startDay int
declare #NextTransactionDate datetime
--Monday
set #TransactionDate = '2011-05-05'
SET #TransactionDay = DATEPART(dw, #TransactionDate)
--Wednesday
set #startDate = '2011-04-27'
set #startDay = datepart(dw,#startDate)
set #NextTransactionDate= DATEADD(DAY, ((#startDay - #TransactionDay) + 7) % 7 ,#TransactionDate);
select #startDay, DATEPART(dw, #NextTransactionDate), #NextTransactionDate
To explain the meat of it, I'm finding the difference in the day-of-week for the startDate and the transactionDate. I add 14 to it because negative numbers modulo positive numbers result in a negative number, which would put your next transaction date in the past (and you don't want that). The worst case is when #startDay is 1 and #TransactionDay is 7 which leads to a difference of -6. Adding 7 ensures that that difference is positive but still in the same equivalence class as the actual difference in the ring n mod 7(sorry... I'm a bit of a math nerd).

Try this:
declare #TransactionDate datetime
declare #startDate datetime
declare #startDay int
declare #transactionDay int
declare #NextTransactionDate datetime
declare #daysToAdd int
--Monday
set #TransactionDate = '2011-05-02'
set #transactionDay = datepart(dw,#TransactionDate)
--Wednesday
set #startDate = '2011-04-27'
set #startDay = datepart(dw,#startDate)
print #transactionDay
print #startDay
if(#startDay <= #transactionDay)
set #daysToAdd = (#startDay + 7) - #transactionDay
else
set #daysToAdd = #startDay - #transactionDay
set #NextTransactionDate = Dateadd(Day,#daysToAdd,#TransactionDate)
print #NextTransactionDate

I'm not sure I follow what you're saying. I think you're saying that the next #TransactionDate, should be the next occurence of the day of the week that the #startDate falls on.
If that's the case, you could try :
declare #tDay = datepart(w, #transactionDate)
set #NextTransactionDate = DATEADD(w, #startDay-#tDay, #TransactionDate);
I'm not sure what you're doing with the 6 and 7 though... are you trying to make sure the new #TransactionDate is not a weekend? If so, this would need to be slightly modified...

Related

Convert Date to Float looses two days

Good morning
I have an interesting situation:
1 June 2018 = 43252 as Integer
30 May 2018 = 43250 as Integer
I try to convert a date to the first of the respective month (reporting month) with the following code:
DECLARE #InputDate DateTime, #Result Float, #Date DateTime
Set #InputDate = '2018/06/18 23:13:05'
If isDate(#InputDate) = 0
BEGIN
Set #Result = 0
END
ELSE
BEGIN
Set #Date = DATEFROMPARTS(Year(#InputDate), Month(#InputDate), 1)
Set #Result = cast (cast(#Date as datetime) as float)
Select #Date, #Result
END
The result for #Date is '2018-06-01 00:00:00.000' as expected but the result for #Result = 43250 which is 30 May 2018. How does this happen?

datediff not returning what I'm expecting

Anyone know why the following is returning 8? I'm expecting 8 hours 30 minutes, or 8.5?
declare #start_day datetime;
declare #end_day datetime;
declare #start_time datetime;
declare #end_time datetime;
set #start_day = '2014-06-18';
set #end_day = '2014-06-18';
set #start_time = '09:00';
set #end_time = '17:30';
print datediff(hour,#start_day + #start_time, #end_day + #end_time);
Try this, CAST your DATEDIFF of the minutes to float then divide by 60 to get the hours.
declare #start_day datetime;
declare #end_day datetime;
declare #start_time datetime;
declare #end_time datetime;
set dateformat ymd
set #start_day = '2014-06-18';
set #end_day = '2014-06-18';
set #start_time = '09:00';
set #end_time = '17:30';
print cast(datediff(minute,#start_day + #start_time, #end_day + #end_time) as float) / 60;
Try this :
print cast(datediff(mi,#start_day + #start_time, #end_day + #end_time)
as decimal(10,2))/60;
it returns the number of fully elapsed hours.
if you want to have 8.5 return minutes and then divide by 60.0.
You have hour as a datepart, the documentation states:
DATEDIFF
Returns the count (signed integer) of the specified datepart
boundaries crossed between the specified startdate and enddate.
The The DATEDIFF() function returns the time between two dates. And its syntax is
DATEDIFF(datepart,startdate,enddate)
Here in datepart you are mentioning hour so thats why it is printing only hours part

SQL Server : setting two variables month and year for previous month, year roll over safe

I'm trying to basically dynamically set two variables (#month and #year) to be whatever the previous month and year were.
So in today's case #month = 7 and #year = 2012
But I want something safe for the year roll around, so if it's 1/1/2013 I would get #month = 12 and #year = 2012.
Thanks!
This is what I have.
declare #month int
declare #year int
set #month = month (getDate ())-1
set #year = 2012
You can use DATEADD to subtract a month from the current date, then grab the MONTH and YEAR portions:
DECLARE #monthAgo dateTime
DECLARE #month int
DECLARE #year int
SET #monthAgo = DATEADD(month, -1, GETDATE())
SET #month = MONTH(#monthAgo)
SET #year = YEAR(#monthAgo)
Shown in steps. You can modify the value assigned to #Now to test.
DECLARE #Now DateTime = GETDATE();
DECLARE #Then DateTime = DATEADD(Month, -1, #Now);
DECLARE #Month Int = DATEPART(Month, #Then);
DECLARE #Year Int = DATEPART(Year, #Then);
SELECT #Month, #Year;
can you not just add, after what you already have:
if #month = 0
begin
set #month = 12
set #year = #year - 1
end
As a single query, this gives the first day of last month:
select DATEADD(month,DATEDIFF(month,'20010101',CURRENT_TIMESTAMP),'20001201')
You can, if you choose, pull that apart into two separate variables, but why bother? (I assume the rest of what you're doing is working with datetimes also, rather than ints)
The two datetime strings above are selected because they have the desired relationship between them - that the second starts 1 month before the first.
Try this
declare #month int
declare #year int
Declare #dt datetime=getdate()
set #month = DATEPART(mm,DATEADD(mm,-1,#dt))
select #month
set #year = DATEPART(yy,DATEADD(mm,-1,#dt))
select #year

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

To get difference between 2 dates

I have 2 dates. I want to get number of days between 2 dates in storedprocedure.
DateDiff function should do what you need
declare #var1 Datetime
declare #var2 Datetime
set #var1 = '2009-04-01'
set #var2 = '2009-04-16'
SELECT datediff(day,#var1, #var2 )
How about using the dateDiff function ?
eg
DECLARE #Dt INT
SET #Dt = DATEDIFF(dd,#StartDate,#EndDate)
should do the trick ?
Or did I miss something ?
USE tempdb
DECLARE #DATE1 datetime
DECLARE #DATE2 datetime
SET #DATE1 = '01/01/2000'
SET #DATE2 = '02/01/2000'
SELECT DATEDIFF(day, #DATE1, #DATE2)
DATEDIFF is the way to do it
Note that DATEDIFF only concerns itself with the date portion. If times are involved, a converted subtraction might yield better results.
DECLARE #start DATETIME
DECLARE #end DATETIME
SET #start = '20090514 00:00:00'
SET #end = '20090514 23:59:59'
PRINT CONVERT(FLOAT, (#end-#start)) -- 0.999988
PRINT DATEDIFF(DAY,#start,#end) -- 0