Get difference in hours between two dates - mysql

How can I subtract two dates (entry_date from status_change_date) to get hours between them? I do this based on an IF statement where both dates are in YYYY,MM,DD 12:00:00 format
(IF Invoice_Num != next Inv_Num then entry_date - status_change_date else...
It returns an answer in days instead of hours. I also tried using minutes(entry_day) and hours(status_change_date) in Crystal after the code was done, but I still got day values.

declare #startDate datetime
declare #endDate datetime
set #startDate = '2016-12-05 08:05:00';
set #endDate = '2016-12-05 09:52:00';
select CONVERT(varchar(3),DATEDIFF(minute,#startDate, #endDate)/60) + ':' +
RIGHT('0' + CONVERT(varchar(2),DATEDIFF(minute,#startDate,#endDate)%60),2)
as TotalHours
Check this example, get the hours and minutes between to datetime vars

From document TIMESTAMPDIFF(unit,datetime_expr1,datetime_expr2),
SELECT TIMESTAMPDIFF(HOUR, '2016-12-05 12:00:00', '2016-12-06 12:00:00');
This will get you 24 hours.
SQLFiddle Demo

Related

Total Number of days of a Month

I need to write a query which returns No. of days of a Month.
Please understand that I cannot use DATE, and any query having DATE will not work.
I have created a parameter which takes int value. Like January is 1, February is 2 etc.
From the values 1 or 2, I wanted to get the number of days like the number of days of 1 should be 31 and 2 should be 28 or 29.
I am using Ms sql-server-2008.
Help is required.
Regards,
So, you can always build a date using date parts. You may want to validate the input and transform this logic to your needs.
DECLARE #year SMALLINT = 2017;
DECLARE #month TINYINT = 2;
DECLARE #dateFrom DATE = CONVERT(DATE,
CONVERT(CHAR(4), #year) + '-'
+ RIGHT('00' + CONVERT(VARCHAR(2), #month), 2)
+ '-01'
);
DECLARE #dateTo DATE = DATEADD(MONTH, 1, #dateFrom);
SELECT DATEDIFF(DAY, #dateFrom, #dateTo);
-- OR --
If you are really keen to not use any calculation, just a query, store these values in a table and query that table using the input values.

Get sunday date between two date and last day from one month mysql

I want to get all sunday date between two dates and get last day between two date, how can i do that in mysql?
Example :
start date | end date
2017-03-01 | 2017-03-31
then the results are :
2017-03-05
2017-03-12
2017-03-19
2017-03-26
2017-03-31
Start date and end date possible to change, please advise me.
Thank you
Since you now mentioned that you don't have a table for the dates, you could approach it like this if you don't want to add a generic calendar table on your database.
declare #startdate datetime
declare #enddate datetime
DECLARE #startdateLoop datetime
select #startdate = CAST(start as DATE), #enddate = CAST(end_date as DATE) from #t
set #startdateLoop = #startdate
CREATE TABLE #tempCal
(dates datetime)
WHILE #startdateLoop != #enddate
BEGIN
INSERT INTO #tempCal
SELECT #startdateLoop
SET #startdateLoop = DATEADD(dd, 1, #startdateLoop)
END
SELECT * FROM #tempCal
WHERE dates between #startdate and #enddate and DAYOFWEEK(dates) = 1
You may turn this into a procedure if you want to.
Would still be nice if you DO HAVE a calendar table; as Tim has suggested.
MySQL has a DAYOFWEEK() function which would return 1 for any date which is a Sunday:
SELECT date_column
FROM yourTable
WHERE (date_column BETWEEN '2017-03-01' AND '2017-03-31' AND
DAYOFWEEK(date_column) = 1) OR -- any Sunday
date_column = '2017-03-31' -- or the last date in the range
I am assuming that yourTable already has dates in it. If you need help with populating a table with a range of dates, this problem has been covered well before on Stack Overflow, q.v. here:
How to populate a table with a range of dates?
Demo here:
Rextester
SELECT calender FROM calender WHERE calender.calender >='2017-03-01' AND calender.calender <='2017-03-31' AND DAYOFWEEK(calender) = 1 OR calender = '2017-03-31' Group By calender
This is #Tim Answer
Thanks Tim

Given datetime, filter results by month of that datetime

For sql server 2008: what is the best way to filter results, to return only results that are in the same month as a certain date?
The best I could come up with is the following:
-- set up test data
DECLARE #TABLE1 AS TABLE (
ID INT,
STRING VARCHAR(MAX),
DATECOLUMN DATETIME
)
INSERT INTO #TABLE1
SELECT
0 ID,
'TABLE1 0' STRING,
CONVERT(DATETIME, '2016-10-13 12:45:00', 102) DATECOLUMN
UNION ALL SELECT 1, 'TABLE1 1', CONVERT(DATETIME, '2016-9-13 12:45:00', 102)
UNION ALL SELECT 2, 'TABLE1 2', CONVERT(DATETIME, '2016-10-1 00:00:00', 102)
UNION ALL SELECT 3, 'TABLE1 3', CONVERT(DATETIME, '2016-10-31 23:59:59', 102)
-- set up constraint
DECLARE #SOMEDATE DATETIME = CONVERT(DATETIME, '2016-10-13 12:45:00', 102)
-- filter
SELECT * FROM #TABLE1
WHERE MONTH(DATECOLUMN) = MONTH(#SOMEDATE)
Is this the best way?
Your query will return records where the month of DateColumn matches the month of #SomeDate, although (as #Jayvee points out) this would be true regardless of the year. So if that's what you want, your solution is fine.
But you asked whether that was the best solution. I would say no, because this won't take advantage of any index you may have that includes DateColumn.
So this is what I would do, if I were on SQL Server 2008:
declare #someDate datetime = GetDate()
declare #startDate date
declare #endDate date
-- I want the first day of the month, at 12:00:00AM (no time component).
-- The DateAdd expression subtracts days, and converting to the Date data type
-- ensures that I don't have a time component hanging around.
set #startDate = convert(date, DateAdd(day,- DatePart(day, #someDate) + 1, #someDate))
-- I want the first day of the next month. This is easy:
set #endDate = DateAdd(month, 1, #startDate)
-- Here's my actual query, that can take advantage of indexes that include DateColumn:
select *
from Table1
where DateColumn >= #startDate and DateColumn < #endDate
Note that I said >= for start date but < for the end date. That ensures that I'll pick up any date entries for the last day of the month that have a non-zero time component, but won't go into the next month.
The best way for a long-term solution is to create a date dimension table (you can find scripts out there to auto-generate one). The date dim table will just contain a list of dates as far back and forward as you care to go, and it includes columns like DayOfWeek, QuarterOfYear, YYYYMM, etc., so you can join CAST(YOURDATE AS DATE) to the date dim's date and pull nifty date info. Here you can join both of your tables to the date dim and use WHERE t1.YYYYMM = t2.YYYYMM.

How to get week number of the month from the date in sql server 2008

In SQL Statement in microsoft sql server, there is a built-in function to get week number but it is the week of the year.
Select DatePart(week, '2012/11/30') // **returns 48**
The returned value 48 is the week number of the year.
Instead of 48, I want to get 1, 2, 3 or 4 (week number of the month). I think the week number of the month can be achieved by modules with Month Number of this week. For e.g.
Select DATEPART(week, '2012/11/30')%MONTH('2012/11/30')
But I want to know is there other built-in functions to get WeekNumber of the month in MS SQL SERVER.
Here are 2 different ways, both are assuming the week starts on monday
If you want weeks to be whole, so they belong to the month in which they start:
So saturday 2012-09-01 and sunday 2012-09-02 is week 4 and monday 2012-09-03 is week 1 use this:
DECLARE #date date = '2012-09-01'
SELECT (day(datediff(d,0,#date)/7*7)-1)/7+1
If your weeks cut on monthchange so saturday 2012-09-01 and sunday 2012-09-02 is week 1 and monday 2012-09-03 is week 2 use this:
DECLARE #date date = '2012-09-01'
SELECT
datediff(ww,datediff(d,0,dateadd(m,datediff(m,7,#date),0)
)/7*7,dateadd(d,-1,#date))+1
I received an email from Gerald. He pointed out a flaw in the second method. This should be fixed now
I received an email from Ben Wilkins. He pointed out a flaw in the first method. This should be fixed now
DECLARE #DATE DATETIME
SET #DATE = '2013-08-04'
SELECT DATEPART(WEEK, #DATE) -
DATEPART(WEEK, DATEADD(MM, DATEDIFF(MM,0,#DATE), 0))+ 1 AS WEEK_OF_MONTH
No built-in function. It depends what you mean by week of month. You might mean whether it's in the first 7 days (week 1), the second 7 days (week 2), etc. In that case it would just be
(DATEPART(day,#Date)-1)/7 + 1
If you want to use the same week numbering as is used with DATEPART(week,), you could use the difference between the week numbers of the first of the month and the date in question (+1):
(DATEPART(week,#Date)- DATEPART(week,DATEADD(m, DATEDIFF(m, 0, #Date), 0))) + 1
Or, you might need something else, depending on what you mean by the week number.
Just look at the date and see what range it falls in.
Range 1-7 is the 1st week, Range 8-14 is the 2nd week, etc.
SELECT
CASE WHEN DATEPART(day,yourdate) < 8 THEN '1'
ELSE CASE WHEN DATEPART(day,yourdate) < 15 then '2'
ELSE CASE WHEN DATEPART(day,yourdate) < 22 then '3'
ELSE CASE WHEN DATEPART(day,yourdate) < 29 then '4'
ELSE '5'
END
END
END
END
Similar to the second solution, less code:
declare #date datetime = '2014-03-31'
SELECT DATEDIFF(week,0,#date) - (DATEDIFF(week,0,DATEADD(dd, -DAY(#date)+1, #date))-1)
Check this out... its working fine.
declare #date as datetime = '2014-03-10'
select DATEPART(week,#date) - DATEPART(week,cast(cast(year(#date) as varchar(4))+'-' + cast(month(#date) as varchar(2)) + '-01' as datetime))+1
WeekMonth = CASE WHEN (DATEPART(day,TestDate) - datepart(dw,TestDate))>= 22 THEN '5'
WHEN (DATEPART(day,TestDate) - datepart(dw,TestDate))>= 15 THEN '4'
WHEN (DATEPART(day,TestDate) - datepart(dw,TestDate))>= 8 THEN '3'
WHEN (DATEPART(day,TestDate) - datepart(dw,TestDate))>= 1 THEN '2'
ELSE '1'
END
There is no inbuilt function to get you the week number. I dont think dividing will help you anyway as the number of weeks in a month is not constant.
http://msdn.microsoft.com/en-us/library/bb675168.aspx
I guess you can divide the number(48) by 4 and take the modules of the same and project that as the week number of that month, by adding one to the result.
Here's a suggestion for getting the first and last days of the week for a month:
-- Build a temp table with all the dates of the month
drop table #tmp_datesforMonth
go
declare #begDate datetime
declare #endDate datetime
set #begDate = '6/1/13'
set #endDate = '6/30/13';
WITH N(n) AS
( SELECT 0
UNION ALL
SELECT n+1
FROM N
WHERE n <= datepart(dd,#enddate)
)
SELECT DATEADD(dd,n,#BegDate) as dDate
into #tmp_datesforMonth
FROM N
WHERE MONTH(DATEADD(dd,n,#BegDate)) = MONTH(#BegDate)
--- pull results showing the weeks' dates and the week # for the month (not the week # for the current month)
select MIN(dDate) as BegOfWeek
, MAX(dDate) as EndOfWeek
, datediff(week, dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, dDate), 0)), 0), dDate) as WeekNumForMonth
from #tmp_datesforMonth
group by datediff(week, dateadd(week, datediff(week, 0, dateadd(month, datediff(month, 0, dDate), 0)), 0), dDate)
order by 3, 1
A dirty but easy one liner using Dense_Rank function. Performance WILL suffer, but effective none the less.
DENSE_RANK()over(Partition by Month(yourdate),Year(yourdate) Order by Datepart(week,yourdate) asc) as Week
Here is the query that brings the week number on whatever the startday and endday of the week it may be.
SET DATEFIRST 2
DECLARE #FROMDATE DATE='12-JAN-2015'
-- Get the first day of month
DECLARE #ALLDATE DATE=DATEADD(month, DATEDIFF(month, 0, #FROMDATE), 0)
DECLARE #FIRSTDATE DATE
;WITH CTE as
(
-- Get all dates in that month
SELECT 1 RNO,CAST(#ALLDATE AS DATE) as DATES
UNION ALL
SELECT RNO+1, DATEADD(DAY,1,DATES )
FROM CTE
WHERE DATES < DATEADD(MONTH,1,#ALLDATE)
)
-- Retrieves the first day of week, ie, if first day of week is Tuesday, it selects first Tuesday
SELECT TOP 1 #FIRSTDATE = DATES
FROM CTE
WHERE DATEPART(W,DATES)=1
SELECT (DATEDIFF(DAY,#FIRSTDATE,#FROMDATE)/7)+1 WEEKNO
For more information I have answered for the below question. Can check that.
How do I find week number of a date according to DATEFIRST
floor((day(#DateValue)-1)/7)+1
Here you go....
Im using the code below..
DATEPART(WK,#DATE_INSERT) - DATEPART(WK,DATEADD(DAY,1,DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#DATE_INSERT),0)))) + 1
Try Below Code:
declare #dt datetime='2018-03-15 05:16:00.000'
IF (Select (DatePart(DAY,#dt)%7))>0
Select (DatePart(DAY,#dt)/7) +1
ELSE
Select (DatePart(DAY,#dt)/7)
There is an inbuilt option to get the week number of the year
**select datepart(week,getdate())**
You can simply get week number by getting minimum week number of month and deduct it from week number. Suppose you have a table with dates
select
emp_id, dt , datepart(wk,dt) - (select min(datepart(wk,dt))
from
workdates ) + 1 from workdates
Solution:
declare #dt datetime='2018-03-31 05:16:00.000'
IF (Select (DatePart(DAY,#dt)%7))>0
Select (DatePart(DAY,#dt)/7) +1
ELSE
Select (DatePart(DAY,#dt)/7)
declare #end_date datetime = '2019-02-28';
select datepart(week, #end_date) - datepart(week, convert(datetime, substring(convert(nvarchar, convert(datetime, #end_date), 127), 1, 8) + '01')) + 1 [Week of Month];
Here is the tried and tested solution for this query in any situation - like if 1st of the month is on Friday , then also this will work -
select (DATEPART(wk,#date_given)-DATEPART(wk,dateadd(d,1-day(#date_given),#date_given)))+1
above are some solutions which will fail if the month's first date is on Friday , then 4th will be 2nd week of the month
Logic here works as well 4.3 weeks in every month. Take that from the DATEPART(WEEK) on every month but January. Just another way of looking at things. This would also account for months where there is a 5th week
DECLARE #date VARCHAR(10)
SET #date = '7/27/2019'
SELECT CEILING(DATEPART(WEEK,#date)-((DATEPART(MONTH,#date)-1)*4.3333)) 'Week of Month'
Below will only work if you have every week of the month represented in the select list. Else the rank function will not work, but it is a good solution.
SELECT DENSE_RANK() OVER (PARTITION BY MONTH(DATEFIELD)
ORDER BY DATEPART(WEEK,DATEFIELD) ASC) AS WeekofMont
try this one
declare #date datetime = '20210928'
select convert(int,(((cast(datepart(day,#date) as decimal(4,2))/7)-(1.00/7.00))+1.00))
select datepart(week,#date)-datepart(week,dateadd(day,1,eomonth(dateadd(m,-1,#date))))+1
or
select datepart(week,#date)-datepart(week,dateadd(d,-datepart(d,#date)+1,#date))+1
steps:
1,get the first day of month
2,week of year of the date - week of year of the first day of the month
3,+1
2023-1-1 is sunday
SET DATEFIRST 1;
DECLARE #date date = '2023-1-02';
select datepart(week,#date)-datepart(week,dateadd(day,1,eomonth(dateadd(m,-1,#date))))+1
return 2
SET DATEFIRST 7;
DECLARE #date date = '2023-1-02';
select datepart(week,#date)-datepart(week,dateadd(day,1,eomonth(dateadd(m,-1,#date))))+1
return 1
Code is below:
set datefirst 7
declare #dt datetime='29/04/2016 00:00:00'
select (day(#dt)+datepart(WEEKDAY,dateadd(d,-day(#dt),#dt+1)))/7
select #DateCreated, DATEDIFF(WEEK, #DateCreated, GETDATE())

SQL server 2008, datediff returns wrong value

I have two columns of Data type time. I'm using datediff to find the difference in hours.
The problem is when I try to find the difference between 00:00:00 to 06:00:00, it returns -18.
How can I fix it?
note: I need to calculate more difference with this so I can't just divide it with -3
my function- (datediff(HOUR, startHour, endHour))*60
Thanks in advance
You are not comparing 00:00:00 to 06:00:00. You have some date component
This gives -18 as an example
DECLARE #starthour datetime = '00:00:00';
DECLARE #endhour datetime = '18991231 06:00:00';
SELECT #starthour, #endhour, DATEDIFF(hour, #starthour, #endhour);
SET #starthour = '20120507 00:00:00';
SET #endhour = '20120506 06:00:00';
SELECT #starthour, #endhour, DATEDIFF(hour, #starthour, #endhour);
Reverse the parameters:
my function- (datediff(HOUR, endHour, startHour))*60
Edit:
The function DATEDIFF works with dates and for some reason, it thinks you're subtracting 6AM - Midnight (next day), which is 18 hours.
The following code sample works fine for me in SQL 2008, so you need to check your data type to make sure you're using TIME and not DATETIME or SMALLDATETIME.
declare #t1 time
set #t1 = '00:00:00'
declare #t2 time
set #t2 = '06:00:00'
select datediff(hour, #t1, #t2)
-- returns 6
Syntax:
DATEDIFF (datepart, startdate, enddate )
Examples:
SELECT DATEDIFF(hour, '00:00:00', '06:00:00');
Result: 6
SELECT DATEDIFF(hour, '00:00:00', '06:00:00')*60;
Result: 360
Refer DATEDIFF (Transact-SQL)
I'm late to the game, but I faced a similar problem.
DATEDIFF(HOUR,'23:00:00','06:00:00')
Result: -17
Reversing the two times (as suggested by another answer above) does not represent the time frame I want to capture. I don't want to know how many hours are between 6am and 11pm. I want 11pm to 6am.
To resolve this, wrap the DATEDIFF() in a CASE statement and add 24 when the start time is greater than the end time:
DECLARE #startTime TIME(0) = '23:00:00';
DECLARE #endTime TIME(0) = '06:00:00';
SELECT CASE WHEN #startTime > #endTime THEN 24 + DATEDIFF(HOUR,#startTime,#endTime) ELSE DATEDIFF(HOUR,#startTime,#endTime) END
Result: 7