I have a table with four columns:
id;
datefrom;
dateto;
user id.
I need to calculate the difference between datefrom and dateto (datefrom-dateto) in hours, add this difference into additional column. The main thing is that some cells of dateto are empty. In this case I should take "dateto" as current date and time.
The second thing is to add column with if statment. If the difference between datefrom and dateto more than 3 hours than 1, else 0.
Now I can calculate only differences in hours. The main problem is with empty cells and additional column with statement when hours more than 3
select id, DateFrom, DateTo, UserId,
(Datefrom-DateTO) as hours
from table
order by id
enter image description here
Here is a good example for MS SQL:
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SET #StartDate ='2007-06-05'
SET #EndDate ='2007-08-05'
SELECT DATEDIFF(Hour, #StartDate, #EndDate) AS NewDate
--Return Value = 1464 Hour
SELECT DATEDIFF(minute, #StartDate, #EndDate) AS NewDate
--Return Value = 87840 minute
SELECT DATEDIFF(second, #StartDate, #EndDate) AS NewDate
--Return Value = 5270400 second
You will need some Control Flow Functions.
With the select, you will need:
SELECT id, datefrom, dateto, userid
You can use IFNULL(), if dateto is NULL, then it will return CURDATE():
IFNULL(dateto, CURDATE())
And one IF(condition, truth, false), but first, you will need the diference in hours. You can calculate with some Date and Time Functions, you will get the diference between the dates, convert it to seconds, and divide by 3600):
TIME_TO_SEC(TIMEDIFF(IFNULL(dateto, CURDATE()), datefrom)) / 3600
Now, check if it's bigger than 3:
IF(TIME_TO_SEC(TIMEDIFF(IFNULL(dateto, CURDATE()), datefrom)) / 3600 > 3, 1, 0)
At the end, it will be like:
SELECT
id,
datefrom,
dateto,
userid,
TIME_TO_SEC(TIMEDIFF(IFNULL(dateto, CURDATE()), datefrom)) / 3600
IF(TIME_TO_SEC(TIMEDIFF(IFNULL(dateto, CURDATE()), datefrom)) / 3600 > 3, 1, 0),
FROM table;
thanks all.
I wrote code in Periscope. I dont know why but I can use there some functions as TIME_TO_SEC, TIMEDIFF, TIMESTAMPDIFF.
The final code is below.
SELECT id
, DateFrom
, DateTo
, UserId
, CASE
WHEN DateFrom is null OR (DateFrom - DateTo) < '0 days 00:00:00'
THEN (NOW() - DateTo)
ELSE (DateFrom - DateTo)
END as hours
, CASE
WHEN (DateFrom IS NULL AND (NOW() - DateTo) > '0 days 03:00:00') OR (DateFrom is not null and ((DateFrom - DateTo) > '0 days 03:00:00') OR (DateFrom - DateTo) < '0 days 00:00:00')
THEN 1
ELSE 0
END as Attribute
Related
I have a table that has a column "Created" as a datetime.
I'm trying to query to check if the time for the Created value is between two times.
The Created datetime for the first row is '2013-07-01 00:00:00.000' (Midnight) and I'm trying to query for items with a time between 11PM and 7AM.
select *
from MyTable
where CAST(Created as time) between '23:00:00' and '06:59:59'
But no results are returned.
Do I need to convert my times to datetimes?
I suspect you want to check that it's after 11pm or before 7am:
select *
from MyTable
where CAST(Created as time) >= '23:00:00'
or CAST(Created as time) < '07:00:00'
select *
from MyTable
where CAST(Created as time) not between '07:00' and '22:59:59 997'
I had a very similar problem and want to share my solution
Given this table (all MySQL 5.6):
create table DailySchedule
(
id int auto_increment primary key,
start_time time not null,
stop_time time not null
);
Select all rows where a given time x (hh:mm:ss) is between start and stop time. Including the next day.
Note: replace NOW() with the any time x you like
SELECT id
FROM DailySchedule
WHERE
(start_time < stop_time AND NOW() BETWEEN start_time AND stop_time)
OR
(stop_time < start_time AND NOW() < start_time AND NOW() < stop_time)
OR
(stop_time < start_time AND NOW() > start_time)
Results
Given
id: 1, start_time: 10:00:00, stop_time: 15:00:00
id: 2, start_time: 22:00:00, stop_time: 12:00:00
Selected rows with NOW = 09:00:00: 2
Selected rows with NOW = 14:00:00: 1
Selected rows with NOW = 11:00:00: 1,2
Selected rows with NOW = 20:00:00: nothing
This should also work (even in SQL-Server 2005):
SELECT *
FROM dbo.MyTable
WHERE Created >= DATEADD(hh,23,DATEADD(day, DATEDIFF(day, 0, Created - 1), 0))
AND Created < DATEADD(hh,7,DATEADD(day, DATEDIFF(day, 0, Created), 0))
DEMO
WITH CTE as
(
SELECT CAST(ShiftStart AS DATETIME) AS ShiftStart,
CASE WHEN ShiftStart > ShiftEnd THEN CAST(ShiftEnd AS DATETIME) +1
ELSE CAST(ShiftEnd AS DATETIME) END AS ShiftEnd
FROM **TABLE_NAME**
)
SELECT * FROM CTE
WHERE
CAST('11:00:00' AS DATETIME) BETWEEN ShiftStart AND ShiftEnd -- Start of Shift
OR CAST('23:00:00' AS DATETIME) BETWEEN ShiftStart AND ShiftEnd -- End of Shift
Let us consider a table which stores the shift details
Please check the SQL queries to generate table and finding the schedule based on an input(time)
Declaring the Table variable
declare #MyShiftTable table(MyShift int,StartTime time,EndTime time)
Adding values to Table variable
insert into #MyShiftTable select 1,'01:17:40.3530000','02:17:40.3530000'
insert into #MyShiftTable select 2,'09:17:40.3530000','03:17:40.3530000'
insert into #MyShiftTable select 3,'10:17:40.3530000','18:17:40.3530000'
Creating another table variable with an additional field named "Flag"
declare #Temp table(MyShift int,StartTime time,EndTime time,Flag int)
Adding values to temporary table with swapping the start and end time
insert into #Temp select MyShift,case when (StartTime>EndTime) then EndTime else StartTime end,case when (StartTime>EndTime) then StartTime else EndTime end,case when (StartTime>EndTime) then 1 else 0 end from #MyShiftTable
Creating input variable to find the Shift
declare #time time=convert(time,'10:12:40.3530000')
Query to find the shift corresponding to the time supplied
select myShift from #Temp where (#time between StartTime and EndTime and
Flag=0) or (#time not between StartTime and EndTime and Flag=1)
select * from dbMaster oMaster where ((CAST(GETDATE() as time)) between (CAST(oMaster.DateFrom as time)) and
(CAST(oMaster.DateTo as time)))
Please check this
Should be AND instead of OR
select *
from MyTable
where CAST(Created as time) >= '23:00:00'
AND CAST(Created as time) < '07:00:00'
I have an issue regarding date calculations.
I have a datetime column called CreatedLocalTime date with this format: 2015-11-15 19:48:50.000
I need to retrieve a new column called Prod_Date with:
if “CreatedLocalTime” between
(CreatedLocalTime 7 AM)
& (CreatedLocalTime+1 7 AM)
return CreatedLocalTime date with DD/MM/YYYY format
On other words, today production = sum of yesterday from 7 AM till today at 7 AM.
Any help using case?
For day 7AM to day+1 7AM, you can try:
SELECT CAST(CreatedLocalTime as date)
...
FROM ...
WHERE ...
CreatedLocalTime >= DATEADD(hour, 7, CAST(CAST(CreatedLocalTime as date) as datetime))
AND
CreatedLocalTime < DATEADD(hour, 31, CAST(CAST(CreatedLocalTime as date) as datetime))
...
For previous day 7AM to day 7AM, replace 7 by -14 and 31 by 7.
Another way..
SELECT CASE WHEN CreatedLocalTime BETWEEN DATEADD(HOUR, 7,
CAST(CAST (CreatedLocalTime AS DATE) AS DATETIME))
AND DATEADD(HOUR, 31,
CAST(CAST (CreatedLocalTime AS DATE) AS DATETIME))
THEN REPLACE(CONVERT(NVARCHAR, CreatedLocalTime, 103), ' ', '/')
END AS CreatedLocalTime
You can write the else part for this, if needed
It looks like you want somthing along the lines of
DECLARE #StartDateTime Datetime
DECLARE #EndDateTime Datetime
SET #EndDateTime = DATEADD(hour, 7,convert(datetime,convert(date,getdate())) )
SET #StartDateTime = DATEADD(day, -1, #EndDateTime )
--Print out the variables for demonstration purposes
PRINT '#StartDateTime = '+CONVERT(nchar(19), #StartDateTime,120)
PRINT '#EndDateTime = '+CONVERT(nchar(19), #EndDateTime,120)
SELECT SUM (Production) AS Prod_Date FROM YourSchema.YourTable WHERE CreatedLocalTime >= #StartDateTime AND CreatedLocalTime < #EndDateTime
But you could also look at it as all the times which after you remove 7 hours from them are yesterday
SELECT SUM (Production) AS Prod_Date
FROM YourSchema.YourTable
WHERE DATEDIFF(day,DATEADD(hour, -7, CreatedLocalTime ))) = 1
The First version will be more efficient as the query will only have to do the date arithmetic once at the start while the second involved executing DATEDIFF and DATEADD for every record. This will be slower on large amounts of data.
The Gold plated solution would be to add a computed column to your table
ALTER TABLE YourSchema.YourTable ADD EffectiveDate AS CONVERT(date, DATEDIFF(day,DATEADD(hour, -7, CreatedLocalTime ))))
And then an index on that column
CREATE INDEX IX_YourTable_EffectiveDate ON YourSchema.YourTable (EffectiveDate )
So you can write
DECLARE #YesterDay date = DATEADD(day,-1, getdate())
SELECT SUM (Production) AS Prod_Date
FROM YourSchema.YourTable
WHERE EffectiveDate = #YesterDay
name amount date
---------------------------------------
xxx 1000 2014-04-20 12:53:23.983
yyy 1500 2014-04-25 12:53:23.983
My output like this:
name amount date
--------------------------------------
xxx 1000 2014-04-20 12:53:23.983
My query:
alter proc K_VM_GetTaxdetails
as
begin
select name, amount, date
from K_VM_TaxDetails
where DATEADD(day, -15, GETDATE()) = date
end
I have tried like this but I am not getting required output.
If I have a date = 2014-04-20 12:53:23.983 in my table, I want to display all data before 15 days from that date.
How can I write in where condition?
This displays all rows in the last 15 days:
declare #now = select cast(floor(cast(getdate() as float)) as datetime); -- truncate time from datetime
select name, amount, date from K_VM_TaxDetails
where date >= dateadd(day, -15, #now);
This displays all rows for single day 15 days ago:
declare #now = select cast(floor(cast(getdate() as float)) as datetime); -- truncate time from datetime
select name,amount,date from K_VM_TaxDetails
where date >= dateadd(day, -15, #now) and
date < dateadd(day, -14, #now);
This will give you all data from the day 15 days ago
alter proc K_VM_GetTaxdetails
as
begin
declare #d datetime = dateadd(day, datediff(day, -15, getdate()), 0)
select name, amount, date
from K_VM_TaxDetails
where date >= #d -- retrieve from
and date < dateadd(day, 1, #d) -- retrieve to
end
Shows dates at least 15 days older than the current date:
select name,amount,date from K_VM_TaxDetails
where date <= DATEADD(day, -15, GETDATE())
I suggest to compare date with only date part and not time as including time in date comparison sometimes provided incorrect result.
Below query removes time part and compare only date.
select name, amount, date
from K_VM_TaxDetails
where (convert(date,[date]) >= DATEADD(day, -15, convert(date,GETDATE())) and convert(date,[date]) <= convert(date,GETDATE()))
alter proc K_VM_GetTaxdetails
as
begin
select name, amount, date
from K_VM_TaxDetails
where DATEADD(day, -15, SYSDATETIME()) = date
end
I have a table that has a column "Created" as a datetime.
I'm trying to query to check if the time for the Created value is between two times.
The Created datetime for the first row is '2013-07-01 00:00:00.000' (Midnight) and I'm trying to query for items with a time between 11PM and 7AM.
select *
from MyTable
where CAST(Created as time) between '23:00:00' and '06:59:59'
But no results are returned.
Do I need to convert my times to datetimes?
I suspect you want to check that it's after 11pm or before 7am:
select *
from MyTable
where CAST(Created as time) >= '23:00:00'
or CAST(Created as time) < '07:00:00'
select *
from MyTable
where CAST(Created as time) not between '07:00' and '22:59:59 997'
I had a very similar problem and want to share my solution
Given this table (all MySQL 5.6):
create table DailySchedule
(
id int auto_increment primary key,
start_time time not null,
stop_time time not null
);
Select all rows where a given time x (hh:mm:ss) is between start and stop time. Including the next day.
Note: replace NOW() with the any time x you like
SELECT id
FROM DailySchedule
WHERE
(start_time < stop_time AND NOW() BETWEEN start_time AND stop_time)
OR
(stop_time < start_time AND NOW() < start_time AND NOW() < stop_time)
OR
(stop_time < start_time AND NOW() > start_time)
Results
Given
id: 1, start_time: 10:00:00, stop_time: 15:00:00
id: 2, start_time: 22:00:00, stop_time: 12:00:00
Selected rows with NOW = 09:00:00: 2
Selected rows with NOW = 14:00:00: 1
Selected rows with NOW = 11:00:00: 1,2
Selected rows with NOW = 20:00:00: nothing
This should also work (even in SQL-Server 2005):
SELECT *
FROM dbo.MyTable
WHERE Created >= DATEADD(hh,23,DATEADD(day, DATEDIFF(day, 0, Created - 1), 0))
AND Created < DATEADD(hh,7,DATEADD(day, DATEDIFF(day, 0, Created), 0))
DEMO
WITH CTE as
(
SELECT CAST(ShiftStart AS DATETIME) AS ShiftStart,
CASE WHEN ShiftStart > ShiftEnd THEN CAST(ShiftEnd AS DATETIME) +1
ELSE CAST(ShiftEnd AS DATETIME) END AS ShiftEnd
FROM **TABLE_NAME**
)
SELECT * FROM CTE
WHERE
CAST('11:00:00' AS DATETIME) BETWEEN ShiftStart AND ShiftEnd -- Start of Shift
OR CAST('23:00:00' AS DATETIME) BETWEEN ShiftStart AND ShiftEnd -- End of Shift
Let us consider a table which stores the shift details
Please check the SQL queries to generate table and finding the schedule based on an input(time)
Declaring the Table variable
declare #MyShiftTable table(MyShift int,StartTime time,EndTime time)
Adding values to Table variable
insert into #MyShiftTable select 1,'01:17:40.3530000','02:17:40.3530000'
insert into #MyShiftTable select 2,'09:17:40.3530000','03:17:40.3530000'
insert into #MyShiftTable select 3,'10:17:40.3530000','18:17:40.3530000'
Creating another table variable with an additional field named "Flag"
declare #Temp table(MyShift int,StartTime time,EndTime time,Flag int)
Adding values to temporary table with swapping the start and end time
insert into #Temp select MyShift,case when (StartTime>EndTime) then EndTime else StartTime end,case when (StartTime>EndTime) then StartTime else EndTime end,case when (StartTime>EndTime) then 1 else 0 end from #MyShiftTable
Creating input variable to find the Shift
declare #time time=convert(time,'10:12:40.3530000')
Query to find the shift corresponding to the time supplied
select myShift from #Temp where (#time between StartTime and EndTime and
Flag=0) or (#time not between StartTime and EndTime and Flag=1)
select * from dbMaster oMaster where ((CAST(GETDATE() as time)) between (CAST(oMaster.DateFrom as time)) and
(CAST(oMaster.DateTo as time)))
Please check this
Should be AND instead of OR
select *
from MyTable
where CAST(Created as time) >= '23:00:00'
AND CAST(Created as time) < '07:00:00'
I am looking for an SQL query for the sum of minutes between start and end date for a particular month.
Eg.
I'm looking for the amount of minutes used in February.
Start Date Time: 27-02-13 00:00:00
End Date Time: 05-03-13 00:00:00
Because im only looking for the sum of february it should only give me the sum of 3 days (in minutes) and not the extra 5 days going into march.
I have no way to validate it but it should looks like:
SELECT DATEDIFF(minute, startDate, CASE when endDate > EOMONTH(startDate) THEN EOMONTH(startDate) ELSE endDate END) FROM ...
GL!
I left it in steps to illustrate each process. You can of course easily collapse this down, but I'll leave it up to you to do that.
Here's my solution http://www.sqlfiddle.com/#!3/b4991/1/0
SELECT *
, DATEDIFF(minute, StartDAte, NewEndDate) AS TotalMinutes
FROM
(
SELECT *
, CASE WHEN TempDate > EndDate THEN EndDate ELSE TempDate END AS NewEndDate -- Either EOM or old EndDate, whichever is smaller
FROM
(
SELECT *
, DATEADD(month, 1, CAST(Year + '-' + Month + '-1' AS DATETIME)) AS TempDate -- first day of the next month
FROM
(
select *
, CAST(DATEPART(month, StartDate) AS char(2)) AS Month
, CAST(DATEPART(year, StartDate) AS char(4)) AS Year
from tbl
) t0
) t1
) t2
First I get the year and month from the original StartDate. I then construct a first-of-the-month date from that. I then add one month to that to get me the first-of-the-month of the next month. Then I check if that new date is > or < the previous EndDate. I take the smaller of the two dates. Then I use the original StartDate and whichever is smaller between the TempDate and EndDate to determine my total minutes.
See Also EOMONTH: http://msdn.microsoft.com/en-us/library/hh213020.aspx
Look into using DATEDIFF -- this will just help you to get started:
SELECT DATEDIFF(minute, starttime, endtime)
http://msdn.microsoft.com/en-us/library/ms189794.aspx
To get the last day of the start month, use DATEADD:
SELECT DATEADD(second,-1,DATEADD(month, DATEDIFF(month,0,starttime)+1,0))
SQL Fiddle Demo
I recently had to solve a similar problem, I added two new functions to help with this:
CREATE FUNCTION [dbo].[GREATESTDATE]
(
-- Add the parameters for the function here
#Date1 DATETIME,
#Date2 DATETIME
)
RETURNS DATETIME
AS
BEGIN
IF (#Date1 < #Date2)
RETURN #Date2
ELSE
RETURN #Date1
END
and...
CREATE FUNCTION [dbo].[LEASTDATE]
(
-- Add the parameters for the function here
#Date1 DATETIME,
#Date2 DATETIME
)
RETURNS DATETIME
AS
BEGIN
IF (#Date1 > #Date2)
RETURN #Date2
ELSE
RETURN #Date1
END
Then use them like:
DATEDIFF(D,dbo.GREATESTDATE(#StartDate1,#StartDate2),dbo.LEASTDATE(#EndDate1,#EndDate2))