How Can i Input Hours and minutes in Start and End Date - sql

In my sql query i have to select particular date from start date 00:00:00 to end date 23:59:59. But how could I input the hours and minutes if the date values are not hardcode. They are input in a form in frontend then it run the particular report. Below is my code any ideas?? It should be like this
BETWEEN '2019-06-00 00:00:00' AND '2019-06-10 23:59:59'
$start_date = $_GET['start_date'];
$end_date = $_GET['end_date'];
$sql = "SELECT
outlets.outletname,
outlets.barcode,
invoiceissued.invoiceno,
invoiceissued.total_amount,
invoiceissued.VATAmount,
invoiceissued.date_created,
outlets.businessregistrationno,
outlets.vat
FROM `invoiceissued` , outlets
WHERE
invoiceissued.outletid = outlets.outletsid
and `date_created` BETWEEN ('".$start_date."') AND ('".$end_date."')";

Just get some idea from the below script that How you should handle your start and end date.
SELECT
CAST('2019-06-00' AS DATETIME),
CAST(DATE_ADD('2019-06-10', INTERVAL 1 DAY) AS DATETIME);
/*Added 1 day with the end date so that you can use date < end_date*/
Your query will be something like-
....
WHERE
....
AND `date_created` >= CAST('2019-06-00' AS DATETIME)
AND `date_created` < CAST(DATE_ADD('2019-06-10', INTERVAL 1 DAY) AS DATETIME);
Still if you want to use BETWEEN, the script should be as below-
....
WHERE
....
AND `date_created`
BETWEEN CAST('2019-06-00' AS DATETIME)
AND CAST(CONCAT('2019-06-10',' 23:59:59') AS DATETIME),

Related

How to query records that are within a specific range of TIME datatype? [duplicate]

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'

SELECT TWO TIMES (minutes) that fall across midnight

I need to select registers from a date between a time (23:00 to 02:00, for example), but I dont know how to elaborate a select for that case.
I have two fields (integer value) and only one field for date.
The date field dont record the timestamp, its the application that I use that do that, and there is nothing to do about it. The time is recorded in two fields ("start time" and "end time"), and, sometimes the "end time" cross over midnight.
date | start time | end time
16-08-2016 00:00:00 | 1420 | 90
The time is in minutes, so, start time is 23:40 and end time is 01:30.
My select is starting to get bigger and I'm afraid that what I'm doing is wrong.
EDIT - Query:
SELECT * FROM TABLE WHERE (((1320 >= StartTime OR 1320 <= EndTime) AND EndTime < StartTime AND MyDate <= '17/08/2016') OR
((1350 >= StartTime OR 1350 <= EndTime) AND EndTime < StarTime AND MyDate <= '17/08/2016'))
Use the fields you have to calculate the start and end points as Oracle DATEs (which include both date and time). Then filter as for any other DATE columns.
Like this:
SELECT * FROM
(
-- This inline view gets everything in your table, plus the start_datetime and end_datetime as calculated from your various fields.
SELECT your_table.*, start_date + ( start_time / 1440 ) start_datetime, start_date + case when end_time < start_time then end_time + 1440 else end_time end end_datetime FROM your_table
)
WHERE start_datetime between ... whatever date range you want ...
AND end_datetime between ... whatever date range you want ...
select date, starttime, DATEADD(mi, endtime,Dateadd(mi,starttime, cast(date as datetime))) AS Enddatetime
FROM yourtable
I've put what you're looking for within variables at the top so you only have to enter them once. You can embed them in the query along with the conversion logic, but it's messy.
declare #date datetime, #start int, #end int
select #date = '17/8/2016', #start = 1425, #end = 15
-- convert minutes past midnight
select #end = #end + case when #start > #end then 1440 else 0 end
select *
from Table
where MyDate = #date
and StartTime between #start and #end
and EndTime + case when StartTime > EndTime then 1440 else 0 end between #start and #end
This finds all registers that started and ended within the specified times. Use the below where clause if you also need to find ones that ran during the times but either started before, finished after, or both.
where MyDate = #date
and StartTime < #end
and EndTime + case when StartTime > EndTime then 1440 else 0 end > #start

Sql Query not showing data for selected date

I have datetime field in DB, which stores invoice dates (format is 7/15/2014 12:00:00 AM)
Then I have two datetimepickers, for From date and To date.
I am trying to get it through SQL query
>Where TRDate between #DT1 and #DT2 Order By TRRef DESC
The problem is, If I select 7/15/2014 using datetime picker, it does not show the data for 15th. For this I need to select 14th.
Isn't selected date inclusive?
Thanks
Method1:
You should change input parameters like this
SET #DT1 = CONVERT(varchar(11), #DT1 ,101) + ' 00:00:00'
SET #DT2 = CONVERT(varchar(11), #DT2 ,101) + ' 23:59:57';
Then write search query
Or else use this
Method2
Where TRDate between #DT1 and DateAdd(DD,1,#DT2) Order By TRRef DESC
I don't know what RDBMS you are using but here's a simple tip. You can use >= and < for the comparison but you need to add 1 DAY on the second date.
This is not the correct syntax for adding a day in a date. It depends on what RDBMS you used.
WHERE TRDate >= #DT1 AND TRDate < (#DT2 + 1 DAY)
^ add 1 day
so here's what happened. Assuming you want to get the records between 7/1/2014 12:00:00 AM and 7/15/2014 12:00:00 AM
WHERE TRDate >= '2014-07-01 00:00:00' AND
TRDate < '2014-07-16 00:00:00' -- result for adding 1 day on 15th

Check if a time is between two times (time DataType)

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'

Calculate time difference (only working hours) in minutes between two dates

I need to calculate the number of "active minutes" for an event within a database. The start-time is well known.
The complication is that these active minutes should only be counted during a working day - Monday-Friday 9am-6.30pm, excluding weekends and (known) list of holiday days
The start or "current" time may be outside working hours, but still only the working hours are counted.
This is SQL Server 2005, so T-SQL or a managed assembly could be used.
If you want to do it pure SQL here's one approach
CREATE TABLE working_hours (start DATETIME, end DATETIME);
Now populate the working hours table with countable periods, ~250 rows per year.
If you have an event(#event_start, #event_end) that will start off hours and end off hours then simple query
SELECT SUM(end-start) as duration
FROM working_hours
WHERE start >= #event_start AND end <= #event_end
will suffice.
If on the other hand the event starts and/or ends during working hours the query is more complicated
SELECT SUM(duration)
FROM
(
SELECT SUM(end-start) as duration
FROM working_hours
WHERE start >= #event_start AND end <= #event_end
UNION ALL
SELECT end-#event_start
FROM working_hours
WHERE #event_start between start AND end
UNION ALL
SELECT #event_end - start
FROM working_hours
WHERE #event_end between start AND end
) AS u
Notes:
the above is untested query, depending on your RDBMS you might need date/time functions for aggregating and subtracting datetime (and depending on the functions used the above query can work with any time precision).
the query can be rewritten to not use the UNION ALL.
the working_hours table can be used for other things in the system and allows maximum flexibility
EDIT:
In MSSQL you can use DATEDIFF(mi, start, end) to get the number of minutes for each subtraction above.
Using unreason's excellent starting point, here is a TSQL implementation for SQL Server 2012.
This first SQL populates a table with our work days and times excluding weekends and holidays:
declare #dteStart date
declare #dteEnd date
declare #dtStart smalldatetime
declare #dtEnd smalldatetime
Select #dteStart = '2016-01-01'
Select #dteEnd = '2016-12-31'
CREATE TABLE working_hours (starttime SMALLDATETIME, endtime SMALLDATETIME);
while #dteStart <= #dteEnd
BEGIN
IF datename(WEEKDAY, #dteStart) <> 'Saturday'
AND DATENAME(WEEKDAY, #dteStart) <> 'Sunday'
AND #dteStart not in ('2016-01-01' --New Years
,'2016-01-18' --MLK Jr
,'2016-02-15' --President's Day
,'2016-05-30' --Memorial Day
,'2016-07-04' --Fourth of July
,'2016-09-05' --Labor Day
,'2016-11-11' --Veteran's Day
,'2016-11-24' --Thanksgiving
,'2016-11-25' --Day after Thanksgiving
,'2016-12-26' --Christmas
)
BEGIN
select #dtStart = SMALLDATETIMEFROMPARTS(year(#dteStart),month(#dteStart),day(#dteStart),8,0) --8:00am
select #dtEnd = SMALLDATETIMEFROMPARTS(year(#dteStart),month(#dteStart),day(#dteStart),17,0) --5:00pm
insert into working_hours values (#dtStart,#dtEnd)
END
Select #dteStart = DATEADD(day,1,#dteStart)
END
Now here is the logic that worked to return the minutes as an INT:
declare #event_start datetime2
declare #event_end datetime2
select #event_start = '2016-01-04 8:00'
select #event_end = '2016-01-06 16:59'
SELECT SUM(duration) as minutes
FROM
(
SELECT DATEDIFF(mi,#event_start,#event_end) as duration
FROM working_hours
WHERE #event_start >= starttime
AND #event_start <= endtime
AND #event_end <= endtime
UNION ALL
SELECT DATEDIFF(mi,#event_start,endtime)
FROM working_hours
WHERE #event_start >= starttime
AND #event_start <= endtime
AND #event_end > endtime
UNION ALL
SELECT DATEDIFF(mi,starttime,#event_end)
FROM working_hours
WHERE #event_end >= starttime
AND #event_end <= endtime
AND #event_start < starttime
UNION ALL
SELECT SUM(DATEDIFF(mi,starttime,endtime))
FROM working_hours
WHERE starttime > #event_start
AND endtime < #event_end
) AS u
This correctly returns 1 minute shy of three 9 hour work days
I came here looking for an answer to a very similar question - I needed to get the minutes between 2 dates excluding weekends and excluding hours outside of 08:30 and 18:00. After a bit of hacking around, I think i have it sorted. Below is how I did it. thoughts are welcome - who knows, maybe one day I'll sign up to this site :)
create function WorkingMinutesBetweenDates(#dteStart datetime, #dteEnd datetime)
returns int
as
begin
declare #minutes int
set #minutes = 0
while #dteEnd>=#dteStart
begin
if datename(weekday,#dteStart) <>'Saturday' and datename(weekday,#dteStart)<>'Sunday'
and (datepart(hour,#dteStart) >=8 and datepart(minute,#dteStart)>=30 )
and (datepart(hour,#dteStart) <=17)
begin
set #minutes = #minutes + 1
end
set #dteStart = dateadd(minute,1,#dteStart)
end
return #minutes
end
go
I started working with what Unreason posted and was a great start. I tested this is SQL Server and found not all time was being captured. I think the problem was primarily when the event started and ended the same day. This solution seems to be working well enough for me
CREATE TABLE [dbo].[working_hours](
[wh_id] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[wh_starttime] [datetime] NULL,
[wh_endtime] [datetime] NULL,
PRIMARY KEY CLUSTERED
(
[wh_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE FUNCTION [dbo].[udFWorkingMinutes]
(
#startdate DATETIME
,#enddate DATETIME
)
RETURNS INT
AS
BEGIN
DECLARE #WorkingHours INT
SET #WorkingHours =
(SELECT
CASE WHEN COALESCE(SUM(duration),0) < 0 THEN 0 ELSE SUM(Duration)
END AS Minutes
FROM
(
--All whole days
SELECT ISNULL(DATEDIFF(mi,wh_starttime,wh_endtime),0) AS Duration
FROM working_hours
WHERE wh_starttime >= #startdate AND wh_endtime <= #enddate
UNION ALL
--All partial days where event start after office hours and finish after office hours
SELECT ISNULL(DATEDIFF(mi,#startdate,wh_endtime),0) AS Duration
FROM working_hours
WHERE #startdate > wh_starttime AND #enddate >= wh_endtime
AND (CAST(wh_starttime AS DATE) = CAST(#startdate AS DATE))
AND #startdate < wh_endtime
UNION ALL
--All partial days where event starts before office hours and ends before day end
SELECT ISNULL(DATEDIFF(mi,wh_starttime,#enddate),0) AS Duration
FROM working_hours
WHERE #enddate < wh_endtime
AND #enddate >= wh_starttime
AND #startdate <= wh_starttime
AND (CAST(wh_endtime AS DATE) = CAST(#enddate AS DATE))
UNION ALL
--Get partial day where intraday event
SELECT ISNULL(DATEDIFF(mi,#startdate,#enddate),0) AS Duration
FROM working_hours
WHERE #startdate > wh_starttime AND #enddate < wh_endtime
AND (CAST(#startdate AS DATE)= CAST(wh_starttime AS DATE))
AND (CAST(#enddate AS DATE)= CAST(wh_endtime AS DATE))
) AS u)
RETURN #WorkingHours
END
GO
Alls that is left to do is populate the working hours table with something like
;WITH cte AS (
SELECT CASE WHEN DATEPART(Day,'2014-01-01 9:00:00 AM') = 1 THEN '2014-01-01 9:00:00 AM'
ELSE DATEADD(Day,DATEDIFF(Day,0,'2014-01-01 9:00:00 AM')+1,0) END AS myStartDate,
CASE WHEN DATEPART(Day,'2014-01-01 5:00:00 PM') = 1 THEN '2014-01-01 5:00:00 PM'
ELSE DATEADD(Day,DATEDIFF(Day,0,'2014-01-01 5:00:00 PM')+1,0) END AS myEndDate
UNION ALL
SELECT DATEADD(Day,1,myStartDate), DATEADD(Day,1,myEndDate)
FROM cte
WHERE DATEADD(Day,1,myStartDate) <= '2015-01-01'
)
INSERT INTO working_hours
SELECT myStartDate, myEndDate
FROM cte
OPTION (MAXRECURSION 0)
delete from working_hours where datename(dw,wh_starttime) IN ('Saturday', 'Sunday')
--delete public holidays
delete from working_hours where CAST(wh_starttime AS DATE) = '2014-01-01'
My first post! Be merciful.
Globally, you'd need:
A way to capture the end-time of the event (possibly through notification, or whatever started the event in the first place), and a table to record this beginning and end time.
A helper table containing all the periods (start and end) to be counted. (And then you'd need some supporting code to keep this table up to date in the future)
A stored procedure that will:
iterate over this helper table and find the 'active' periods
calculate the minutes within each active period.
(Note that this assumes the event can last multiple days: is that really likely?)
A different method would be to have a ticking clock inside the event, which checks every time whether the event should be counted at that time, and increments (in seconds or minutes) every time it discovers itself to be active during the relevant period. This would still require the helper table and would be less auditable (presumably).