Date time query SQL SERVER - sql

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. :)

Related

setting time range in SQL Developer

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';

How to compare datetime in SQL Server?

I have to show the date 2018/01/30 if the datetime is between 2018/01/30 04:59:59.000 and 2018/01/31 04:59:59.000
I have a table called DataEntry. I want to move those records by date as per my criteria.
This DataEntry table have TransferTime that datatype is datetime.
As per my criteria if the TransferTime is 2018/01/30 01:30:59.000 then the date should be 2018/01/29
I think you can simply just write like this:
select
case when DATEPART(HOUR,'2018/01/30 01:30:59.000') >= 05 then cast('2018/01/30 01:30:59.000' as date)
else cast(dateadd(Dd,-1,'2018/01/30 01:30:59.000' )as date)
end
This is somewhat of a guess on vague logic, but perhaps using CONVERT and DATEADD?
WITH VTE AS(
SELECT CONVERT(datetime2(3),DT) AS DT
FROM (VALUES('20180130 04:59:59.000'),('20180131 01:00:34.000'),('20180130 01:30:59.000')) V(DT))
SELECT CONVERT(date, DATEADD(SECOND, -17999,DT)) AS D, DT
FROM VTE;
It's worth noting that you, oddly, state that '20180130 04:59:59.000' AND ''20180131 04:59:59.000' should both be on the same day, ('20180130'). This doesn't make any sense, as Days don't overlap like that. Thus the latter time would show '20180131', as it's exactly 24 hours later.
If the former time should actually be '20180129', then change -17999 to -18000, or SECOND,-17999 to HOUR, -5.
this will do too:
select cast(dateadd(second, -17999,Transfertime) as date)
being 17999 = 4hs59m59s in seconds

Using Dates in SQL Server 2012 Query

I'm using SQL Server 2012 and I need to write a query that will extract data greater than a particular date. The date field is called 'CreatedOn" and dates are recorded in this format "2014-08-18 17:02:57.903".
Currently, the date part of my query stands as follows:
WHERE CreatedOn > '2014-08-18'
Problem is extracted data includes those of '2014-08-18'. It's like the > (greater than) is acting like >= (greater than or equal)!
How should I write my query if I need all data, say greater than '2014-08-18'?
Try the following condition. The problem is that 2014-08-18 is really 2014-08-18 00:00:00 (includes the hour), so any date time in that day will be greater.
WHERE CreatedOn >= '2014-08-19'
'2014-08-18' actually means '2014-08-18 00:00:00'
So if you do not want 18th you should put either '2014-08-19' or specify the hours you want your date to be bigger of.
As the others have said it is actually translating to CreatedOn > 2014-08-18 00:00:00
Instead try converting your datetime field to a short ate and compare those.
The 126 in Convert maps to the yyyy-mm-ddThh:mi:ss.mmm format.
WHERE CONVERT(char(10), CreatedOn,126) > '2014-08-18'
It sounds like when you're saying you want records "greater than '2014-08-18' you actually mean "records that occurred past 2014-08-18 23:59:59.999999" - you have to take into account time when working with dates, unless the time is otherwise removed (which in your sample data it was not.
You could do something like the following:
declare #gtDate datetime
set #gtDate = dateadd(d, 1, convert(datetime,convert(varchar(10), '2014-08-18', 101)))
....
WHERE CreatedOn >= #gtDate
Here we're taking your '2014-08-18', convert it to a varchar containing only the date (to help in case '2014-08-18' is ever '2014-08-18 12:00:00 as an example)
Then we convert the varchar back to a date, and add a day to it. In the end the statement says
Give me records that occured on 2014-08-19 or greater
EDIT:
Here's a fiddle demonstrating
http://sqlfiddle.com/#!6/90465/1
Note that we have 4 rows of data potential
insert into sampleData (Created)
select '2014-08-17'
union all select '2014-08-18'
union all select '2014-08-18 12:00:00'
union all select '2014-08-19'
union all select '2014-08-19 15:00:00'
only the bottom 2 rows (2014-08-19 and 2014-08-19 15:00:00) would be returned

Extract min timestamp from string using SQL Server 2008

I am trying to query the minimum datetime from a column that is stored as nvarchar(max). There a a few tricky things with this query (at least for me)
There is more than just the date being stored within each record.
The position of the datetime is relative - although it does always appear in the format **(DD-MM-YY at HH:MM PM
There are multiple datetimes stored in each record - so not only do I need to locate and capture where there is a datetime, I need to find the minimum datetime within the record
I can't just change the format that the data is stored in - there is over a decade of information that is stored this way.
The column is called 'hdresp' - here is sample data:
**(03-Apr-14 at 09:44 AM email sent) -- Billy Bob: Upgrade ordered. **(02-Apr-14 at 04:16 PM email sent) -- Sammy Richards: I can give you another cable to if you think that will help but it just might be time for an upgrade. If you want to go that route I have to ask that you submit another request for New Hardware. **(02-Apr-14 at 03:17 PM email sent) -- Paul Smith: Michael Stop by my desk when you have a second.
What I would like to end up with is a query that identifies 02-Apr-14 at 3:17 PM as the minimum time and converts it to YYYY-MM-DD HH:MM:SS - for example 2014-04-02 15:17:00
Perhaps you could try this approach:
select hdresp, min(ts) as timestamp
from (
select hdresp, cast(substring(hdresp,delta+3,10)+substring(hdresp,delta+15,9) as datetime2) as ts
from (
select
hdresp,
charindex('**(',hdresp,1) as delta
from problem
union
select
hdresp,
charindex('**(',hdresp,1+charindex('**(',hdresp,1)) as delta
from problem
union
select
hdresp,
charindex('**(',hdresp,1+charindex('**(',hdresp,1+charindex('**(',hdresp,1))) as delta
from problem
union
select
hdresp,
charindex('**(',hdresp,1+charindex('**(',hdresp,1+charindex('**(',hdresp,1+charindex('**(',hdresp,1)))) as delta
from problem
) as temp1
where delta > 0
) as temp2
group by hdresp
;
See example here: http://sqlfiddle.com/#!3/a1a99/1
If there are more than 4 possible timestamps in a hdresp, just add more UNION SELECT... sections.
Thank you everyone for your help!
I ended up using this to extract and convert the minimum time from a string:
SELECT CONVERT(datetime, REPLACE(LEFT(RIGHT(hdresp, PATINDEX('%(**%', REVERSE(hdresp)) - 1), 21), 'at ', ''))
from tblhdmain
where hdindex = 211458
Which gave me the result:
2014-04-02 15:17:00.000

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