setting time range in SQL Developer - sql

I am working on a dataset that contains car accidents and their time of occurrence. (the data set exists in SQL Server under the name accident).
I have a column that is in date format. I would like to extract the time from the column. Then add a new column called lightining_period label the time as daytime or nighttime. My problem is with setting a range for the times, as I get the wrong label each time I run the code.
Different lighting periods (daytime: 6AM - 5:59PM and nighttime 6PM - 5:59AM).
[1]First I wrote this code to extract the time from accident_date_time and store it in a new column time.
create table lightiningPeriod as
select to_char(accident_date_time,'HH:MMAM') as time
from accident.accident;
[2]Then, I altered the table to add the column lightining_label where I want to store the labels daytime/nighttime.
alter table lightiningPeriod add (
lightining_label varchar2(20)
);
[3]Finally, I used Update statement to change the values of lightining_label according to time ranges. But the tables come out wrong. I tried using between, to_date, cast, convert but none of them worked.
update lightiningPeriod
set lightining_label='daytime'
where time >= '06:00AM'
and time <= '5:59PM';
below is a sample of the output I get which shows wrong labels.
time lightining_label
06:04AM daytime
11:04AM daytime
01:04AM (null)
10:04AM daytime
10:04AM daytime
04:04PM (null)
07:04PM daytime
01:04PM (null)

It looks like the time column is using a string type (VARCHAR, NVARCHAR) instead of TIME. So you compare string values instead of time values.
You can use the following using CONVERT to compare the string values like time values:
UPDATE lightiningPeriod
SET lightining_label = CASE WHEN CONVERT(TIME, [time]) BETWEEN CONVERT(TIME, '06:00AM') AND CONVERT(TIME, '5:59PM') THEN 'daytime' ELSE 'nighttime' END
demo on dbfiddle.uk
I recommend to store the time values on a column using TIME data type.

This is a tweak on Sebastian's answer. In SQL Server, you can use a computed column:
ALTER TABLE lightiningPeriod
ADD lightining_label AS (CASE WHEN CONVERT(TIME, [time]) >= CONVERT(TIME, '06:00:00') AND CONVERT(TIME, [time]) < CONVERT(TIME, '18:00:00')
THEN 'daytime' ELSE 'nighttime'
END)
Then the label is calculated when you query the table, so it is always correct.

Thank you all, I have solved the query doing this:
update lightiningPeriod
set lightining_label='daytime'
where to_char(accident_date_time, 'hh24:mi') >= '06:00'
and to_char(accident_date_time, 'hh24:mi') <= '17:59';

Related

Date time query SQL SERVER

I have Date Column Order_Date In date Time format Isdat
14/05/2018 13:13:06 This is format) , I need To Extract Today's Order before 14:00 P:M 'O' Clock and in Second Column I want to extract order after 15:00 P:M i.e Time from 15:00 P:M till 23:00 P:M in SQL SERVER,
Date Is in 24:00 Hor Format.
In output Order_date Should be 'yyyy-MM-dd hh:mm:ss ' Format
Like the others have said, the first thing you need to do is fix your data; storing a date as a varchar is a bad design choice. Always use a data type that is representative of you data; stores dates as a date, numbers as an int/decimal, etc.
According to the [documentation] there is no style code for dd/MM/yyyy hh:mm:ss, however, a quick SQL as below told me that style code 103 does work:
DECLARE #date varchar(50) = '31/05/2017 19:12:56';
WITH N AS (
SELECT 1 AS i
UNION ALL
SELECT i + 1
FROM N
WHERE I + 1 <= 150)
SELECT I, TRY_CONVERT(datetime2(0),#Date,I) AS Conversion
FROM N
OPTION (MAXRECURSION 150);
So, firstly, let's fix that data of yours. So, let's add the new column in and drop your old one.
ALTER TABLE YourTable ADD OrderDate datetime2(0);
UPDATE YourTable
SET OrderDate = CONVERT(datetime2(0),YourDateColumn,103);
GO
ALTER TABLE YourTable DROP COLUMN YourDateColumn;
EXEC sp_rename 'dbo.YourTable.OrderDate','YourDateColumn','COLUMN';
Ok, now we've got rid of your awful datatype, and got your new column. Good.
Now, you want to specifically query time here; if you're doing that, ideally you want to separate the value of the time and date out. Using something like WHERE CONVERT(time, YourDateColumn) BETWEEN '14:00' AND '15:00' makes the query non-SARGHable. Thus let's use a couple of computed columns for that:
ALTER TABLE YourTable ADD OrderDate AS CONVERT(date, YourDateColumn);
ALTER TABLE YourTable ADD OrderTime AS CONVERT(time, YourDateColumn);
Now, to your question at hand: "I need To Extract Today's Order before 14:00 P:M 'O' Clock and in Second Column I want to extract order after 15:00 P:M i.e Time from 15:00 P:M till 23:00 P:M in SQL SERVER". honestly, this is non-sensical; putting different orders based on time in different columns? I have no idea what you mean here, I'm afraid, and I have no sample data or expected results to work with. Thus, instead, i'll show you how to return orders after 14:00 but before '15:00` on a specific date:
SELECT *
FROM YourTable YT
WHERE OrderDate = '20170515'
AND OrderTime >= '14:00'
AND OrderTime < '15:00';
If you need more detail than that, you have a lot of comments asking you for more detail; I suggest you have a look at those. :)

Convert time in SQL to 12 hour format WITH seconds on

I have a script that I am using to populate a time dimension table and I would like to have a column for the time in 12 hour format.
I know this can be done by doing something along the lines of
SELECT CONVERT(varchar(15),[FullTime],100)
Where [FullTime] is a column containing a TIME field in HH:MM:SS format.
But this gives the following result 2:30pm and I would like 2:30:47PM, note the inclusion of seconds.
I know I could build this up using substrings etc. but I wondered if there was a prettier way of doing it.
Thanks
SELECT GETDATE() 'Today',
CONVERT(VARCHAR(8), [FullTime], 108) 'hh:mi:ss'
Taken from here
This will give you a column 'today' followed by the time value you seek 'hh:mi:ss'
If having also milliseconds is not a problem for you, you can use
SELECT CONVERT(VARCHAR, [FullTime], 109)
Declare #tstTime datetime
set #tstTime = GetDate()
Select
#tstTime
,CONCAT(SUBSTRING(CONVERT(varchar(26), #tstTime, 109),1,20),RIGHT(CONVERT(varchar(26), #tstTime, 109),2))

SQL Server : Comparing Time

I am trying to compare time in my SQL query. However, when I run the query, I get zero result but I can see that in the table, there are records that should appear.
The query is as such:
SELECT *
FROM dbo.Alarms
WHERE StartDate <= '26/08/2015'
AND StartTime <= CONVERT(varchar(5), GETDATE(), 108)
The StartDate is stored in the database as YYYY-MM-DD and it seems to work fine when I query only with the date.
However, when I add the StartTime is when things don't work. StartTime stores the value in the 24 hour clock format.
What am not doing right?
Thanks
Use a correct datetime format:
SELECT *
FROM dbo.Alarms
WHERE StartDate <= '2015-08-26' AND StartTime <= cast(GETDATE() as date)
Don't compare date/time values as strings. The data types are built into the language. Use them.
I have not explicitly used this scenario but comparing dates can be a problem depending on how the fields are compared.
eg: '28/07/2015' is not less than your startdate as 28 > 26.
You could try comparing dates reformatted into a YYYYMMDD format.
Cheers.

Microsoft SQL Server 2008 - Dates

I have a couple of questions in regards to dates in SQL Server.
How do I separate a datetime value "2011-08-10 14:56:17.267" into date and timestamp in two separate columns. Eg. Date "2011-08-10" and timestamp "14:56:17"
I want remove the timestamp from datetime value into "2011-08-10" and still be able to order the data by date (therefore not converted to varchar). Also is there away to change the date value as '10 Aug 2011' and still can sort (not alphabetically but in real date order).
Thank you,
HL
For the first one:
UPDATE atable
SET
DateColumn = CAST(DateTimeColumn AS date),
TimeColumn = CAST(DateTimeColumn AS time)
As for the second one, date display format is something that is unrelated to the date value. You can order the result set by your date column, but in the SELECT clause you can use CONVERT to display the date in the desired format. For example:
SELECT
CONVERT(varchar, DateColumn, 106) AS Date,
…
FROM atable
ORDER BY DateColumn
use CONVERT function with parameters from resource http://www.mssqltips.com/tip.asp?tip=1145
-- simple conversion example:
SELECT CONVERT(VARCHAR(10), GETDATE(), 102) -- for date
SELECT CONVERT(VARCHAR(10), GETDATE(), 8) -- for time

select statement using Between with datetime type does not retrieve all fields?

I'm facing a strange query result and I want to ask you why I'm facing this issue.
I store some datetime data into TestTable as following :
creation_time
-----------------------
2010-07-10 00:01:43.000
2010-07-11 00:01:43.000
2010-07-12 00:01:43.000
This table is created and filled as following :
create table TestTable(creation_time datetime);
Insert into TestTable values('2010-07-10 00:01:43.000');
Insert into TestTable values('2010-07-11 00:01:43.000');
Insert into TestTable values('2010-07-12 00:01:43.000');
when I execute this query , I get two rows only instead of three as I expected:
SELECT * FROM TestTable
WHERE creation_time BETWEEN CONVERT(VARCHAR(10),'2010-07-10',111) -- remove time part
and CONVERT(VARCHAR(10),'2010-07-12',111) -- remove time part
Or if I execute this query , the same issue ..
SELECT * FROM TestTable
WHERE CONVERT(datetime,creation_time,111) BETWEEN CONVERT(VARCHAR(10),'2010-07-10',111) -- remove time part
and CONVERT(VARCHAR(10),'2010-07-12',111) -- remove time part
My Question :
Why the last row ('2010-07-12 00:01:43.000') does not appear in
the result even if I set the date range to cover all the day from 2010-07-10 to 2010-07-12?
I use Sql server 2005 express edition with windows xp 32-bits.
I'm trying to don't use a workaround solution such as increasing the date range to cover additional day to get the days I want.
Thanks .
You need to remove the time part from creation_time as well. Just use the same CONVERT if it works.
Currently you're asking if 2010-07-12 00:01:43.000 is less than 2010-07-12 00:00:00.000, which is not true.
it does not show the date because you have removed the time part, which would make the date equivalent to '2010-07-12 00:00:00.000' and since the last row is greater than this, so it is not displaying in the query results.
Your script should look like this:
SELECT *
FROM TestTable
WHERE creation_time BETWEEN
convert(datetime, convert(char, '2010-07-10', 106))-- remove time part
and **DATEADD**(day, 1, convert(datetime, convert(char, '2010-07-**11**', 106))) -- remove time part and add 1 day
This script will return all between 2010-07-10 00:00:00 and 2010-07-12 00:00:00. Basically this means all items created in 2 days: 2010-07-10 and 2010-07-11.
Converting columns in your table for comparison can be costly and cause indexes to not be used. If you have a million rows in your table and you have an index on creation_time, you will be doing an index scan and converting all million values to a string for comparison.
I find it better to use >= the start date and < (end date + 1 day):
SELECT *
FROM TestTable
WHERE creation_time >= '2010-07-10'
AND creation_time < dateadd(day, 1, '2010-07-12')
And the reason your second one may not work is because format 111 uses slashes ("2010/07/10"), format 120 uses dashes ("2010-07-10"). Your converts aren't doing anything to your start and end date because you are converting a string to varchar, not a date. If you did this, it might work, but I would still recommend not doing the conversion:
SELECT * FROM TestTable
WHERE CONVERT(datetime, creation_time, 111) BETWEEN
CONVERT(VARCHAR(10), CONVERT(datetime, '2010-07-10'), 111) -- remove time part
and CONVERT(VARCHAR(10), CONVERT(datetime, '2010-07-12'), 111) -- remove time part
Date/time inclusive between 7/10/2010 and 7/12/2010:
SELECT * FROM TestTable
WHERE creation_time BETWEEN
CONVERT(VARCHAR,'2010-07-10',101) -- remove time part
and CONVERT(VARCHAR,'2010-07-13',101) -- remove time part