Oracle: how to convert varchar2 to time? - database

How can I convert varchar2 (i.e. string) to timestamp?
The original data
08:00 AM - 06:00 PM
10:00 AM - 04:00 PM
so I can compare between them.
--STORE
CREATE TABLE STORE(
StoreID VARCHAR2(10) NOT NULL,
StoreAddress VARCHAR2(50),
WeekDaysHours VARCHAR2(20),
WeekendHours VARCHAR2(20),
PRIMARY KEY(StoreID));
The values
INSERT INTO STORE VALUES ('S004', 'High Drive', '09:00 AM - 05:00 PM', '08:00 AM - 06:00 PM' );
INSERT INTO STORE VALUES ('S005', 'Snake Rd', '09:00 AM - 09:00 PM', '10:00 AM - 04:00 PM' );

If all values follow the same format and are valid (i.e. you don't have something like 08:BX FZ - #7-25 AM), then use substr (to extract each part of the string) and apply to_date function with appropriate format mask. Date portion will be "today"
[EDIT: no, it won't be "today". Quoting #mathguy's comment (thank you, #mathguy)]
Date portion will not be today. The defaults are "current year" and "current month", but the default "day of the month" is 1. The date portion will be the first day of the current month.
I'm modifying my session just to know what is what:
SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi';
Session altered.
SQL> with test (col) as
2 (select '08:00 AM - 06:00 PM' from dual)
3 select to_date(substr(col, 1, 8), 'hh:mi am') first_part,
4 to_date(substr(col, 13, 8), 'hh:mi pm') second_part
5 from test;
FIRST_PART SECOND_PART
---------------- ----------------
01.05.2021 08:00 01.05.2021 18:00
SQL>
Now that these are dates, you can compare them.

Related

Populate value for new column based on other columns

I have a table in SQL Server 2016, It has 3 columns, (Id,Month,Year) now I want to add a new column to the existing table and its value should be populated based on the Month and Year column's value for existing records and even for new records which are inserted later.
Expected output:
Id Month Year Del_Range
------------------------------------
1 January 2020 2020-01-01
2 February 2020 2020-02-01
3 March 2020 2020-03-01
Query:
CREATE TABLE tempdb..#test
(
Id int,
[Month] varchar(50),
[Year] int,
)
GO
INSERT INTO tempdb..#test (Id, [Month], [Year])
VALUES (1, 'January', 2020),
(2, 'February', 2020),
(3, 'March', '2020')
GO
SELECT * FROM tempdb..#test
GO
ALTER TABLE tempdb..#test
ADD Del_Range DATE
-- Need to add logic to populate value for this column based on value from Month and Year to get expected output
try this below query
alter table #test add Del_Range as convert(date, concat([year], [month], id))
insert into #test(id, month, year)
select 4, 'april', 2020
union
select 4, 'May', 2020
You can try this command.
alter table #test add Del_Range as cast(cast(Year as varchar(4)) + Month + '01' as date)--for first day for a month

How can I add empty rows in SQL SERVER for this example?

Sql Fiddle Example
I have this table structure:
CREATE TABLE Schedule
([Day] varchar(13), [Starts] varchar(57), [Ends] varchar(57))
;
INSERT INTO Schedule
([Day], [Starts], [Ends])
VALUES
('2', '09:00', '15:00'),
('5', '10:00', '12:00'),
('3', '09:00', '18:00')
;
And this simple query to show the current rows:
SELECT
DATENAME(weekday, Day - 1) as days,
Starts,
Ends
FROM
Schedule
order by Day
The last query get this result:
Day Starts Ends
--- ------- ----
Tuesday 09:00 15:00
Wednesday 09:00 18:00
Friday 10:00 12:00
I want to fill the table with the days that doesn't appear in the registers
This is the final result I want to get:
Day Starts Ends
--- ------- ----
Monday NULL NULL
Tuesday 09:00 15:00
Wednesday 09:00 18:00
Thursday NULL NULL
Friday 10:00 12:00
How can I get this?, thanks
I would create an empy base table and do a LEFT JOIN:
CREATE TABLE Schedule
(Day VARCHAR(13), Starts VARCHAR(57), Ends VARCHAR(57));
INSERT INTO Schedule (Day, Starts,Ends)
VALUES
('2', '09:00','15:00'),
('5', '10:00','12:00'),
('3', '09:00','18:00');
CREATE TABLE ScheduleBase
(Day VARCHAR(13), Starts VARCHAR(57), Ends VARCHAR(57));
INSERT INTO ScheduleBase
(Day, Starts, Ends)
VALUES
('1', NULL, NULL),
('2', NULL, NULL),
('3', NULL, NULL),
('4', NULL, NULL),
('5', NULL, NULL)
SELECT SB.Day, S.Starts, S.Ends FROM ScheduleBase AS SB LEFT JOIN Schedule
AS S ON SB.Day = S.Day
You can use this if you do not want to create new table
select
DATENAME(weekday, Day - 1) as days, max(Starts), max(Ends)
from (
SELECT
Day, Starts, Ends
FROM
Schedule
union all
select
*, null, null
from (values (1),(2),(3),(4),(5),(6),(7)) t(d)
) t
group by Day
Alternatively, create a reference table for days then Right Join to your select query.
SELECT DATENAME(WEEKDAY, TBL.days - 1) AS days ,
starts ,
ends
FROM ( SELECT Day days ,
Starts ,
Ends
FROM Schedule
) T
RIGHT JOIN ( SELECT [days]
FROM ( SELECT 1 [days]
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6
UNION
SELECT 7
) S
) TBL ON TBL.days = t.days
Results:
days starts ends
------------ --------- ------------
Monday NULL NULL
Tuesday 09:00 15:00
Wednesday 09:00 18:00
Thursday NULL NULL
Friday 10:00 12:00
Saturday NULL NULL
Sunday NULL NULL
(7 row(s) affected)
You can use a common table expressin to generate a week calendar "table" on the fly:
with range (num) as (
select 1 union all select 2 union all select 3
union all select 4 union all select 5 union all select 6
union all select 7
)
SELECT
DATENAME(weekday, range.num - 1),
Starts,
Ends
FROM
Schedule
right outer join range on range.num = Schedule.day
order by range.num
Fiddle

DATEDIFF with cutoff time

I'm working on a Room Scheduling application. We have this Room Check Out Rule that we need follow. All
room check out should be 12:00 PM. If the check out date is after 12.00 PM it will be considered additional 1 day.
Below is my T-SQL code that returns 5 days.
SELECT DATEDIFF(day, '3/12/2013 12:00:00 PM', '3/17/2013 3:00:00 PM');
If you see the code above the end date is 3:00:00 PM. How can I tweak this code to return 6 days instead of 5?
What if I have this code?
SELECT CEILING(DATEDIFF(SECOND, '3/12/2013 02:00:00 PM' , '3/17/2013 12:50:36 PM') / (24.0 * 60 * 60))
The above code still returns 5 days instead of 6.
SELECT CEILING(DATEDIFF(SECOND, '3/12/2013 12:00:00 PM', '3/17/2013 12:00:01 PM') / (24.0 * 60 * 60))
The correct way is to subtract 12 hours from StartDate and EndDate, then take a day-diff + 1:
declare #dateStart as datetime, #dateEnd as datetime
set #dateStart = cast('20130301 11:59:59 AM' as datetime)
set #dateEnd = cast('20130301 12:01:01 PM' as datetime)
select
#dateStart,
#dateEnd
select days = 1 + datediff(d,#dateStart,#dateEnd)
select
days = 1 + datediff(d, dateadd(hh, -12, #dateStart), dateadd(hh, -12, #dateEnd))
returns this:
----------------------- -----------------------
2013-03-01 11:59:59.000 2013-03-01 12:01:01.000
days
-----------
1
days
-----------
2
Clearly the second formula is correct, not the first.
Perhaps you can count hours:
SELECT DATEDIFF(hour, '3/12/2013 12:00:00 PM', '3/17/2013 3:00:00 PM');
Therefore, 123 > 120 (or divided by 24 - 5.125 > 5) accounts for 6 days.

SQL query for in between data in a table

Please give me right answer for this question
This is the table time_names and its structure:
time_id time_name
------- ----------
1 5:00 AM
2 5:15 AM
3 5:30 AM
4 5:45 AM
5 6:00 AM
6 6:15 AM
... .....
... .....
70 10:15 PM
71 10:30 PM
72 10:45 PM
73 11:00 PM
74 11:15 PM
75 11:30 PM
76 11:45 PM
time_id is INT, time_name is varchar datatype.
Here I want show only 8:30 AM to 11:00 PM between all data
Please give me any query
Since you're on SQL Server 2008, you can simply cast the time_name to a TIME datatype:
SELECT time_id, time_name
FROM dbo.time_names
WHERE CAST(time_name AS TIME) BETWEEN '08:30 AM' AND '11:00 PM'
But seriously: if you store a time value - WHY aren't you using the appropriate TIME datatype for it??
select time_name between will not work, because it's string comparison. You have to use time_id or convert time, for example like this
select *
from time_names
where convert(nvarchar(8), convert(datetime, time_name, 109), 108) between '08:30' and '23:00'
Here I'm converting time from string to real date time and then converting it into 24 hours format, so you can use string compare.
you also can use time type
select *
from time_names
where convert(time, time_name, 109) between '08:30' and '23:00'
http://msdn.microsoft.com/en-us/library/ms187928.aspx
I also have to say that this table design looks really bad. You have to store date and time in the columns with apropriate types.
I´m not a SQL user but try to convert the 'time_name' to DateTime data type and use a select between DateTime1 AND DateTime2
You can use the following query
CREATE table #Time(
time_id int PRIMARY key,
time_name varchar(255))
INSERT INTO #Time values(1, '5:00 AM')
INSERT INTO #Time values(2, '5:15 AM')
INSERT INTO #Time values(3, '5:30 AM')
INSERT INTO #Time values(4, '5:45 AM')
INSERT INTO #Time values(5, '6:00 AM')
INSERT INTO #Time values(6, '6:15 AM')
INSERT INTO #Time values(7, '6:30 AM')
INSERT INTO #Time values(8, '6:45 AM')
select * from #Time
where CAST(time_name as datetime) between CAST('5:30 AM' as datetime) and CAST('6:00 AM' as datetime)
DROP TABLE #Time

Getting the 'date' out of a DateTime field in SQL Server

I have a date column where the date is displayed in the format 2009-11-18 10:55:28.370.
I just want to get the date (not time) out of that value. How do I do that?
If you're using SQL Server 2008, there is now a DATE datatype. Makes it a lot more natural!
SELECT CONVERT(Date, GETDATE())
it is called "flooring a datetime", do it like this to remove just the time (this is the fastest method, faster than using CONVERT() or CAST() sting formatting):
DECLARE #datetime datetime;
SET #datetime = '2008-09-17 12:56:53.430';
SELECT DATEADD(day,DATEDIFF(day,0,#datetime),0)
OUTPUT:
-----------------------
2008-09-17 00:00:00.000
(1 row(s) affected)
here is how to do it for other parts of a datetime:
--Floor a datetime
DECLARE #datetime datetime;
SET #datetime = '2008-09-17 12:56:53.430';
SELECT '0 None', #datetime -- none 2008-09-17 12:56:53.430
UNION SELECT '1 Second',DATEADD(second,DATEDIFF(second,'2000-01-01',#datetime),'2000-01-01') -- Second: 2008-09-17 12:56:53.000
UNION SELECT '2 Minute',DATEADD(minute,DATEDIFF(minute,0,#datetime),0) -- Minute: 2008-09-17 12:56:00.000
UNION SELECT '3 Hour', DATEADD(hour,DATEDIFF(hour,0,#datetime),0) -- Hour: 2008-09-17 12:00:00.000
UNION SELECT '4 Day', DATEADD(day,DATEDIFF(day,0,#datetime),0) -- Day: 2008-09-17 00:00:00.000
UNION SELECT '5 Month', DATEADD(month,DATEDIFF(month,0,#datetime),0) -- Month: 2008-09-01 00:00:00.000
UNION SELECT '6 Year', DATEADD(year,DATEDIFF(year,0,#datetime),0) -- Year: 2008-01-01 00:00:00.000
ORDER BY 1
PRINT' '
PRINT 'Note that when you are flooring by the second, you will often get an arithmetic overflow if you use 0. So pick a known value that is guaranteed to be lower than the datetime you are attempting to floor'
PRINT 'this always uses a date less than the given date, so there will be no arithmetic overflow'
SELECT '1 Second',DATEADD(second,DATEDIFF(second,DATEADD(day,DATEDIFF(day,0,#datetime),0)-1,#datetime),DATEADD(day,DATEDIFF(day,0,#datetime),0)-1) -- Second: 2008-09-17 12:56:53.000
OUTPUT:
-------- -----------------------
0 None 2008-09-17 12:56:53.430
1 Second 2008-09-17 12:56:53.000
2 Minute 2008-09-17 12:56:00.000
3 Hour 2008-09-17 12:00:00.000
4 Day 2008-09-17 00:00:00.000
5 Month 2008-09-01 00:00:00.000
6 Year 2008-01-01 00:00:00.000
(7 row(s) affected)
Note that when you are flooring by the second, you will often get an arithmetic overflow if you use 0. So pick a known value that is guaranteed to be lower than the datetime you are attempting to floor
this always uses a date less than the given date, so there will be no arithmetic overflow
-------- -----------------------
1 Second 2008-09-17 12:56:53.000
(1 row(s) affected)
If i got your question right,
select convert(varchar, creation_date , 103) as creation_date from tablename
Look at CAST and CONVERT
Here:
SELECT creation_date
FROM risks
WHERE creation_date = GETDATE()
This will return all creation_date values stored in the risks table that are exactly the same as what is returned by the GETDATE() function. I am assuming that the data type of creation_date is Date.
You just need to include creation_date in your select clause like this:
select id, creation_date from risks where creation_date = getdate()
You can always use the month/day/year functions to return it:
declare #date datetime
set #date = '1/1/10 12:00 PM'
select cast(month(#date) as varchar) + '/' + cast(day(#date) as varchar) + '/' + cast(year(#date) as varchar) as theDate

Resources