How to convert a timestamp from one timezone to other - sql

I have a table with TIMESTAMP column in Teradata.
I want to consider the values stored in this column as if they are from 'America Pacific' timezone and convert it into GMT timestamp.
I tried,
select timestamp_col,
timestamp_col at 'GMT' timestamp_col_gmt,
timestamp_col at 'America Pacific' timestamp_col_pac,
from table_name;
timestamp_col timestamp_col_gmt timestamp_col_pac
------------------- ------------------------- -------------------------
2014-10-27 22:02:29 2014-10-27 22:02:29+00:00 2014-10-27 15:02:29-07:00
2013-11-28 22:55:27 2013-11-28 22:55:27+00:00 2013-11-28 14:55:27-08:00
2014-09-19 00:23:56 2014-09-19 00:23:56+00:00 2014-09-18 17:23:56-07:00
2013-06-18 00:39:18 2013-06-18 00:39:18+00:00 2013-06-17 17:39:18-07:00
But it looks like, it is considering timestamp_col as originally being in GMT.
What I want is something like this.
timestamp_col timestamp_col_gmt
------------------- -------------------
2013-11-28 22:55:27 2013-11-29 06:55:27 --date belongs to PST. 8 hour difference
2014-10-27 22:02:29 2014-10-28 05:02:29 --date belongs to PDT. 7 hour difference
2014-09-19 00:23:56 2014-09-19 07:23:56 --date belongs to PDT. 7 hour difference
2013-06-18 00:39:18 2013-06-18 07:39:18 --date belongs to PDT. 7 hour difference
I want to consider daylight savings also.
Using dnoeth's query, for sometime during the timezone switch, the result is incorrect.
with recursive y(timestamp_col) as
(
select timestamp_val
from x
union all
select timestamp_col + interval '1' hour
from y
where timestamp_col <= timestamp'2015-03-08 10:00:00'
),
x(timestamp_val) as
(
select timestamp'2015-03-08 00:00:00'
)
select timestamp_col,
cast(
(timestamp_col at 'America Pacific')
- (extract(timezone_hour from (timestamp_col at 'America Pacific')) * interval '1' hour)
as timestamp(0)) timestamp_col_gmt
from y
order by timestamp_col;
timestamp_col timestamp_col_gmt
------------------- -------------------
2015-03-08 00:00:00 2015-03-08 08:00:00 --PST, correct
2015-03-08 01:00:00 2015-03-08 09:00:00 --PST, correct
2015-03-08 02:00:00 2015-03-08 10:00:00 --Can be ignored
2015-03-08 03:00:00 2015-03-08 11:00:00 --PDT, should be 10:00:00
2015-03-08 04:00:00 2015-03-08 12:00:00 --PDT, should be 11:00:00
2015-03-08 05:00:00 2015-03-08 13:00:00 --PDT, should be 12:00:00
2015-03-08 06:00:00 2015-03-08 14:00:00 --PDT, should be 13:00:00
2015-03-08 07:00:00 2015-03-08 15:00:00 --PDT, should be 14:00:00
2015-03-08 08:00:00 2015-03-08 16:00:00 --PDT, should be 15:00:00
2015-03-08 09:00:00 2015-03-08 17:00:00 --PDT, should be 16:00:00
2015-03-08 10:00:00 2015-03-08 17:00:00 --PDT, correct
2015-03-08 11:00:00 2015-03-08 18:00:00 --PDT, correct
with recursive y(timestamp_col) as
(
select timestamp_val
from x
union all
select timestamp_col + interval '1' hour
from y
where timestamp_col <= timestamp'2015-11-01 10:00:00'
),
x(timestamp_val) as
(
select timestamp'2015-11-01 00:00:00'
)
select timestamp_col,
cast(
(timestamp_col at 'America Pacific')
- (extract(timezone_hour from (timestamp_col at 'America Pacific')) * interval '1' hour)
as timestamp(0)) timestamp_col_gmt
from y
order by timestamp_col;
timestamp_col timestamp_col_gmt
------------------- -------------------
2015-11-01 00:00:00 2015-11-01 07:00:00 --PDT, correct
2015-11-01 01:00:00 2015-11-01 08:00:00 --PDT, correct
2015-11-01 02:00:00 2015-11-01 09:00:00 --PST, should be 10:00:00
2015-11-01 03:00:00 2015-11-01 10:00:00 --PST, should be 11:00:00
2015-11-01 04:00:00 2015-11-01 11:00:00 --PST, should be 12:00:00
2015-11-01 05:00:00 2015-11-01 12:00:00 --PST, should be 13:00:00
2015-11-01 06:00:00 2015-11-01 13:00:00 --PST, should be 14:00:00
2015-11-01 07:00:00 2015-11-01 14:00:00 --PST, should be 15:00:00
2015-11-01 08:00:00 2015-11-01 15:00:00 --PST, should be 16:00:00
2015-11-01 09:00:00 2015-11-01 17:00:00 --PST, correct
2015-11-01 10:00:00 2015-11-01 18:00:00 --PST, correct
2015-11-01 11:00:00 2015-11-01 19:00:00 --PST, correct

Teradata stores Timestamps normalized to GMT/UTC/00:00 and displays them based on the session timezone.
Your system or user seems to be set to GMT as default.
This should return the expected data:
Get the data based on the 'America Pacific' time zone, subtract the time zone hour and cast it back to a Timestamp.
CAST((timestamp_col AT 'America Pacific')
- (EXTRACT(TIMEZONE_HOUR FROM (timestamp_col AT 'America Pacific')) * INTERVAL '1' HOUR)
AS TIMESTAMP(0))
Edit:
This returns the correct values for the switch to DST:
CAST(
(timestamp_col AT 'America Pacific')
- (EXTRACT(TIMEZONE_HOUR FROM ((timestamp_col + INTERVAL '7' HOUR) AT 'America Pacific')) * INTERVAL '1' HOUR)
AS TIMESTAMP(0)) timestamp_col_gmt
When it's applied to the switch back from DST:
2014-11-02 01:00:00 2014-11-02 08:00:00
2014-11-02 02:00:00 2014-11-02 10:00:00

Related

Aggregate time from 15-minute interval to single hour in SQL

I have below table structure in SQL Server:
StartDate Start End Sales
==============================================
2020-08-25 00:00:00 00:15:00 291.4200
2020-08-25 00:15:00 00:30:00 401.1700
2020-08-25 00:30:00 00:45:00 308.3300
2020-08-25 00:45:00 01:00:00 518.3200
2020-08-25 01:00:00 01:15:00 247.3700
2020-08-25 01:15:00 01:30:00 115.4700
2020-08-25 01:30:00 01:45:00 342.3800
2020-08-25 01:45:00 02:00:00 233.0900
2020-08-25 02:00:00 02:15:00 303.3400
2020-08-25 02:15:00 02:30:00 11.9000
2020-08-25 02:30:00 02:45:00 115.2400
2020-08-25 02:45:00 03:00:00 199.5200
2020-08-25 06:00:00 06:15:00 0.0000
2020-08-25 06:15:00 06:30:00 45.2400
2020-08-25 06:30:00 06:45:00 30.4800
2020-08-25 06:45:00 07:00:00 0.0000
2020-08-25 07:00:00 07:15:00 0.0000
2020-08-25 07:15:00 07:30:00 69.2800
Is there a way to group above data into one hour interval instead of 15 minute interval?
It has to be based on start and end columns.
Thanks,
Maybe something like the following using datepart?
select startdate, DatePart(hour,start) [Hour], Sum(sales) SalesPerHour
from t
group by startdate, DatePart(hour,start)

Oracle sql create agenda

I have a table with interval dates and times. Can i create a full list with this data?
Table example:
Start_Date, End_Date, Start_Time, End_Time, Interval
01-jun-2021 02-jun-2021 08:00 10:00 30
03-jun-2021 04-jun-2021 10:00 12:00 15
Result:
01-jun-2021 08:00
01-jun-2021 08:30
01-jun-2021 09:00
01-jun-2021 09:30
02-jun-2021 08:00
02-jun-2021 08:30
02-jun-2021 09:00
02-jun-2021 09:30
03-jun-2021 10:00
03-jun-2021 10:15
03-jun-2021 10:30
03-jun-2021 11:00
03-jun-2021 11:15
03-jun-2021 11:30
03-jun-2021 11:45
04-jun-2021 10:00
04-jun-2021 10:15
04-jun-2021 10:30
04-jun-2021 11:00
04-jun-2021 11:15
04-jun-2021 11:30
04-jun-2021 11:45
Thanks.
This is a handy place to use a recursive CTE:
with cte (start_date, end_date, interval) as (
select to_date(start_date||start_time, 'DD-Mon-YYYYHH24:MI'), to_date(end_date||end_time, 'DD-Mon-YYYYHH24:MI'), interval
from t
union all
select cte.start_date + cte.interval * interval '1' minute, end_date, interval
from cte
where cte.start_date < end_date
)
select cast(start_date as timestamp)
from cte
order by start_date;
Here is a db<>fiddle.
You can use a recursive CTE, but the logic has to skip to the next day when you reach the end time; so this works:
with rcte (date_time, end_date, start_int, end_int, step_int) as (
select
start_date + to_dsinterval('0 ' || start_time || ':00'),
end_date,
to_dsinterval('0 ' || start_time || ':00'),
to_dsinterval('0 ' || end_time || ':00'),
interval * interval '1' minute
from your_table
union all
select
case
when date_time + step_int < trunc(date_time) + end_int
then date_time + step_int
else trunc(date_time) + interval '1' day + start_int
end,
end_date,
start_int,
end_int,
step_int
from rcte
where date_time + step_int < end_date + end_int
)
select date_time
from rcte
order by date_time
DATE_TIME
-------------------
2021-06-01 08:00:00
2021-06-01 08:30:00
2021-06-01 09:00:00
2021-06-01 09:30:00
2021-06-02 08:00:00
2021-06-02 08:30:00
2021-06-02 09:00:00
2021-06-02 09:30:00
2021-06-03 10:00:00
2021-06-03 10:15:00
2021-06-03 10:30:00
2021-06-03 10:45:00
2021-06-03 11:00:00
2021-06-03 11:15:00
2021-06-03 11:30:00
2021-06-03 11:45:00
2021-06-04 10:00:00
2021-06-04 10:15:00
2021-06-04 10:30:00
2021-06-04 10:45:00
2021-06-04 11:00:00
2021-06-04 11:15:00
2021-06-04 11:30:00
2021-06-04 11:45:00
db<>fiddle showing the anchor member including converting the times and interval to real day to second intervals types for later use; the anchor and recursive members with all the intermediate columns; and finally just this version with a single column.
You can format the resulting date value however you want, of course.

Processing data set into 30 minute values

I have a data set in the following format -
ID START_TIME END_TIME VAL
1 30-APR-2018 00:00:00 01-MAY-2018 00:00:00 423
2 01-MAY-2018 00:00:00 01-MAY-2018 17:15:00 455
3 01-MAY-2018 17:15:00 03-MAY-2018 00:00:00 455
Expected Output -
This data set should be broken down into 30 min interval values, however if there are records which are not at '00' or '30' minute point then they should be considered as part of this process (as shown for record with START_TIME/END_TIME = '17:15:00')
ID START_TIME END_TIME VAL
1 30-APR-2018 00:00:00 30-APR-2018 00:30:00 423
1 30-APR-2018 00:30:00 30-APR-2018 01:00:00 423
1 30-APR-2018 01:00:00 30-APR-2018 01:30:00 423
..
..
..
1 30-APR-2018 23:00:00 30-APR-2018 23:30:00 423
1 30-APR-2018 23:30:00 01-MAY-2018 00:00:00 423
2 01-MAY-2018 00:00:00 01-MAY-2018 00:30:00 455
2 01-MAY-2018 00:30:00 01-MAY-2018 01:00:00 455
..
..
..
..
2 01-MAY-2018 16:30:00 01-MAY-2018 17:00:00 455
2 01-MAY-2018 17:00:00 01-MAY-2018 17:15:00 455
3 01-MAY-2018 17:15:00 03-MAY-2018 17:30:00 455
3 01-MAY-2018 17:30:00 03-MAY-2018 18:00:00 455
..
..
..
3 02-MAY-2018 23:00:00 02-MAY-2018 23:30:00 455
3 02-MAY-2018 23:30:00 03-MAY-2018 00:00:00 455
What I have tried so far -
CREATE TABLE TESTT
(
ID NUMBER(8,3),
START_TIME DATE,
END_TIME DATE,
VAL NUMBER(8,3)
);
INSERT INTO TESTT VALUES (1, TO_DATE('30-APR-2018 00:00:00','DD-MON-YYYY HH24:MI:SS'), TO_DATE('01-MAY-2018 00:00:00','DD-MON-YYYY HH24:MI:SS'), 423);
INSERT INTO TESTT VALUES (2, TO_DATE('01-MAY-2018 00:00:00','DD-MON-YYYY HH24:MI:SS'), TO_DATE('01-MAY-2018 17:15:00','DD-MON-YYYY HH24:MI:SS'), 455);
INSERT INTO TESTT VALUES (3, TO_DATE('01-MAY-2018 17:15:00','DD-MON-YYYY HH24:MI:SS'), TO_DATE('03-MAY-2018 00:00:00','DD-MON-YYYY HH24:MI:SS'), 455);
COMMIT;
CREATE TABLE TESTT_OUTPUT AS
SELECT * FROM TESTT WHERE 1=2;
CREATE SEQUENCE TESTT_SEQ MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 NOCACHE NOORDER NOCYCLE NOPARTITION;
BEGIN
FOR R IN (SELECT * FROM TESTT)
LOOP
INSERT INTO TESTT_OUTPUT(id, START_TIME, END_TIME, VAL)
SELECT TESTT_SEQ.nextval, R.START_TIME + (LEVEL - 1)/48 AS START_TIME, R.START_TIME + LEVEL/48 AS END_TIME, R.VAL FROM
DUAL
CONNECT BY LEVEL <= ROUND((R.END_TIME - R.START_TIME)*48);
COMMIT;
END LOOP;
END;
/
SELECT * FROM TESTT_OUTPUT;
1 30-APR-2018 00:00:00 30-APR-2018 00:30:00 423
2 30-APR-2018 00:30:00 30-APR-2018 01:00:00 423
3 30-APR-2018 01:00:00 30-APR-2018 01:30:00 423
..
..
..
47 30-APR-2018 23:00:00 30-APR-2018 23:30:00 423
48 30-APR-2018 23:30:00 01-MAY-2018 00:00:00 423
49 01-MAY-2018 00:00:00 01-MAY-2018 00:30:00 455
50 01-MAY-2018 00:30:00 01-MAY-2018 01:00:00 455
..
..
..
82 01-MAY-2018 16:30:00 01-MAY-2018 17:00:00 455
83 01-MAY-2018 17:00:00 01-MAY-2018 17:30:00 455
84 01-MAY-2018 17:15:00 01-MAY-2018 17:45:00 455
85 01-MAY-2018 17:45:00 01-MAY-2018 18:15:00 455
86 01-MAY-2018 18:15:00 01-MAY-2018 18:45:00 455
87 01-MAY-2018 18:45:00 01-MAY-2018 19:15:00 455
..
..
..
141 02-MAY-2018 21:45:00 02-MAY-2018 22:15:00 455
142 02-MAY-2018 22:15:00 02-MAY-2018 22:45:00 455
143 02-MAY-2018 22:45:00 02-MAY-2018 23:15:00 455
144 02-MAY-2018 23:15:00 02-MAY-2018 23:45:00 455
145 02-MAY-2018 23:45:00 03-MAY-2018 00:15:00 455
With this approach any data with the minute value other than '00' or '30' will still be processed the same way by adding 30 mins to it and the final result does not have the point in time data for '00' or '30' minute value.
Hope this makes sense.
Any inputs on how to translate the data in the expected format will be extremely helpful. Thanks!
It seems rather inelegant, but this;
select id,
greatest(start_time,
adj_start_time + numtodsinterval(30 * (level - 1), 'MINUTE')) as start_time,
least(end_time,
adj_start_time + numtodsinterval(30 * level, 'MINUTE')) as end_time
from (
select id,
start_time,
end_time,
trunc(start_time, 'HH')
+ numtodsinterval(
case when extract(minute from cast(start_time as timestamp)) < 30 then 0
else 30
end, 'MINUTE') as adj_start_time
from testt
)
connect by level <= ceil((end_time - start_time - 1/86400) / (30/1440))
and prior id = id
and prior dbms_random.value is not null
order by id, start_time;
seems to get the result you want, generating 145 rows:
ID START_TIME END_TIME
---------- ------------------- -------------------
1 2018-04-30 00:00:00 2018-04-30 00:30:00
1 2018-04-30 00:30:00 2018-04-30 01:00:00
1 2018-04-30 01:00:00 2018-04-30 01:30:00
...
1 2018-04-30 22:30:00 2018-04-30 23:00:00
1 2018-04-30 23:00:00 2018-04-30 23:30:00
1 2018-04-30 23:30:00 2018-05-01 00:00:00
2 2018-05-01 00:00:00 2018-05-01 00:30:00
2 2018-05-01 00:30:00 2018-05-01 01:00:00
2 2018-05-01 01:00:00 2018-05-01 01:30:00
...
2 2018-05-01 16:00:00 2018-05-01 16:30:00
2 2018-05-01 16:30:00 2018-05-01 17:00:00
2 2018-05-01 17:00:00 2018-05-01 17:15:00
3 2018-05-01 17:15:00 2018-05-01 17:30:00
3 2018-05-01 17:30:00 2018-05-01 18:00:00
3 2018-05-01 18:00:00 2018-05-01 18:30:00
...
3 2018-05-02 22:30:00 2018-05-02 23:00:00
3 2018-05-02 23:00:00 2018-05-02 23:30:00
3 2018-05-02 23:30:00 2018-05-03 00:00:00
The inline view gets the real columns plus the nominal 30-minute window for the start -i.e., for 17:15 it gets 17:00, as adj_start_time. The hierarchical query adds 30-minute intervals to that, and uses least and greatest to get the original start/end time if they are not exactly on the half-hour.
For your insert you can replace the original ID with an analytic row_number() rather than using a sequence, and include the val:
insert into testt_output(id, start_time, end_time, val)
select row_number() over (order by id, level),
greatest(start_time,
adj_start_time + numtodsinterval(30 * (level - 1), 'MINUTE')) as start_time,
least(end_time,
adj_start_time + numtodsinterval(30 * level, 'MINUTE')) as end_time,
val
from (
select id,
start_time,
end_time,
val,
trunc(start_time, 'HH')
+ numtodsinterval(
case when extract(minute from cast(start_time as timestamp)) < 30 then 0
else 30
end, 'MINUTE') as adj_start_time
from testt
)
connect by level <= ceil((end_time - start_time - 1/86400) / (30/1440))
and prior id = id
and prior dbms_random.value is not null;
145 rows inserted.
select * from testt_output;
ID START_TIME END_TIME VAL
---------- ------------------- ------------------- ----------
1 2018-04-30 00:00:00 2018-04-30 00:30:00 423
2 2018-04-30 00:30:00 2018-04-30 01:00:00 423
...
47 2018-04-30 23:00:00 2018-04-30 23:30:00 423
48 2018-04-30 23:30:00 2018-05-01 00:00:00 423
49 2018-05-01 00:00:00 2018-05-01 00:30:00 455
50 2018-05-01 00:30:00 2018-05-01 01:00:00 455
...
82 2018-05-01 16:30:00 2018-05-01 17:00:00 455
83 2018-05-01 17:00:00 2018-05-01 17:15:00 455
84 2018-05-01 17:15:00 2018-05-01 17:30:00 455
85 2018-05-01 17:30:00 2018-05-01 18:00:00 455
...
144 2018-05-02 23:00:00 2018-05-02 23:30:00 455
145 2018-05-02 23:30:00 2018-05-03 00:00:00 455
db<>fiddle demo.

How to add leading zero in a number in Oracle with to_number function

create or replace FUNCTION OT_TIMMING_CHECK
(V_OT_ROOM_ID NUMBER,V_OPERATION_DATE DATE,V_START_TIME VARCHAR2,
V_END_TIME VARCHAR2)
RETURN NUMBER AS
V_STATUS_1 VARCHAR2(10);
V_STATUS_2 VARCHAR2(10);
V_STATUS_3 VARCHAR2(10);
V_STATUS_4 VARCHAR2(10);
V_STATUS_5 VARCHAR2(10);
V_STATUS_6 VARCHAR2(10);
C_END_TIME NUMBER;
C_START_TIME NUMBER;
F_OPERATION_DATE DATE;
V_COUNT NUMBER :=0;
b_start_time varchar(10);
BEGIN
SELECT OPERATION_DATE INTO F_OPERATION_DATE FROM OT_THEATRE_STATUS_TBL1
WHERE OPERATION_DATE = V_OPERATION_DATE AND ROWNUM<2 ;
SELECT (case when (substr(V_START_TIME,1,instr(V_START_TIME,':')-1))='00'
then 24
else to_number(substr(V_START_TIME,1,instr(V_START_TIME,':')-1)) end) INTO
C_START_TIME from dual;
SELECT (case when (substr(V_END_TIME,1,instr(V_END_TIME,':')-1))='00' then
24 else to_number(substr(V_END_TIME,1,instr(V_END_TIME,':')-1)) end) INTO
C_END_TIME from dual;
IF V_OT_ROOM_ID=1 AND F_OPERATION_DATE = V_OPERATION_DATE THEN
WHILE (C_START_TIME < C_END_TIME)
LOOP
SELECT STATUS_1 INTO V_STATUS_1 FROM OT_THEATRE_STATUS_TBL1
WHERE START_TIME=concat(to_char(C_START_TIME),':00:00')
AND END_TIME= REPLACE(concat(to_char(C_START_TIME+1),':00:00'),24,'00');
IF(V_STATUS_1 ='Booked' OR V_STATUS_1='Pending') then
RETURN 1;
ELSE
C_START_TIME:= TO_CHAR(C_START_TIME+1);
V_COUNT:=V_COUNT+1;
end if;
END LOOP;
RETURN 0;
END IF ;
END;
Database structure is like this
V_START_TIME V_END_TIME OPERATION_Date STATUS_1 OT_ROOM_ID_1
01:00:00 01:00:00 24-Mar-17 AVAILABLE 1
02:00:00 02:00:00 24-Mar-17 LAPSED 1
03:00:00 03:00:00 24-Mar-17 AVAILABLE 1
04:00:00 04:00:00 24-Mar-17 AVAILABLE 1
05:00:00 05:00:00 24-Mar-17 AVAILABLE 1
06:00:00 06:00:00 24-Mar-17 AVAILABLE 1
07:00:00 07:00:00 24-Mar-17 AVAILABLE 1
08:00:00 08:00:00 24-Mar-17 AVAILABLE 1
09:00:00 09:00:00 24-Mar-17 AVAILABLE 1
10:00:00 10:00:00 24-Mar-17 AVAILABLE 1
11:00:00 11:00:00 24-Mar-17 AVAILABLE 1
12:00:00 12:00:00 24-Mar-17 AVAILABLE 1
13:00:00 13:00:00 24-Mar-17 BOOKING 1
14:00:00 14:00:00 24-Mar-17 AVAILABLE 1
15:00:00 15:00:00 24-Mar-17 AVAILABLE 1
16:00:00 16:00:00 24-Mar-17 AVAILABLE 1
17:00:00 17:00:00 24-Mar-17 AVAILABLE 1
18:00:00 18:00:00 24-Mar-17 AVAILABLE 1
19:00:00 19:00:00 24-Mar-17 AVAILABLE 1
20:00:00 20:00:00 24-Mar-17 AVAILABLE 1
21:00:00 21:00:00 24-Mar-17 AVAILABLE 1
22:00:00 22:00:00 24-Mar-17 AVAILABLE 1
23:00:00 23:00:00 24-Mar-17 AVAILABLE 1
00:00:00 00:00:00 24-Mar-17 AVAILABLE 1
Earlier V_START_TIME like '1:00:00:00' but now it is leading with 0. Then problem comes. Now it is returning null. How to come out from this problem.
Number won't be having leading zero's
Can you try the following:
LPAD(to_number(SUBSTR('01:00:00',1,instr('01:00:00',':')-1)),2, 0)
reference:
How to display the leading zero's in a number of oracle
yes, try it
SELECT (
CASE
WHEN (SUBSTR('01:00:00',1,instr('01:00:00',':')-1))='00'
THEN '24'
ELSE LPAD(SUBSTR('01:00:00',1,instr('01:00:00',':')-1),2,'0')
END)
FROM dual;

SQL Multiple record : Time Scheduler

I have problem about combining tables in store procedure.
Note : field "Time" is varchar
First table (tbTime)
Time
08:00:00
08:30:00
09:00:00
09:30:00
10:00:00
10:30:00
11:00:00
11:30:00
12:00:00
12:30:00
13:00:00
13:30:00
14:00:00
14:30:00
15:00:00
15:30:00
16:00:00
16:30:00
17:00:00
17:30:00
18:00:00
18:30:00
19:00:00
19:30:00
20:00:00
Second table (tbClassRsv)
select * from tbclassrsv where transdate='2014-02-05 00:00:00' and status<>'DEL'
transDate time until status studentCode tutor class description userID
2014-02-05 16:48:14 17:48:14 OPN ET-7201 ET-444 ROOM 01 try ADMIN
I want the result with condition schedule like this
Time Student
08:00:00 -
08:30:00 -
09:00:00 -
09:30:00 -
10:00:00 -
10:30:00 -
11:00:00 -
11:30:00 -
12:00:00 -
12:30:00 -
13:00:00 -
13:30:00 -
14:00:00 -
14:30:00 -
15:00:00 -
15:30:00 -
16:00:00 -
16:30:00 ET-7201
17:00:00 ET-7201
17:30:00 ET-7201
18:00:00 ET-7201
18:30:00 -
19:00:00 -
19:30:00 -
20:00:00 -
Thanks for reading or answer ^_^
GBU
I`ve tried this
select t.time,
isnull(
(select c.studentCode
from tbclassrsv c
where c.transdate='2014-02-05 00:00:00'
and c.class='ROOM 01'
and c.status<>'DEL'
and t.time>=c.time
and t.time<=c.until
),'-') [Student]
The result is....
Time Student
08:00:00 -
08:30:00 -
09:00:00 -
09:30:00 -
10:00:00 -
10:30:00 -
11:00:00 -
11:30:00 -
12:00:00 -
12:30:00 -
13:00:00 -
13:30:00 -
14:00:00 -
14:30:00 -
15:00:00 -
15:30:00 -
16:00:00 -
16:30:00 -
17:00:00 ET-7201
17:30:00 ET-7201
18:00:00 -
18:30:00 -
19:00:00 -
19:30:00 -
20:00:00 -
Try this. you were not converting your varchar times to datetime so that your time comparisons would work.
select t.time,
isnull(
(select c.studentCode
from tbClassRsv c
where c.transdate='2014-02-05 00:00:00'
and c.class='ROOM 01'
and c.status<>'DEL'
and DateAdd(MINUTE, 30, Convert(datetime, t.time))>= Convert(datetime, c.time)
and Convert(datetime, t.time) <= Convert(datetime, c.until)
),'-') from [tbTime] t
What you need to do is round c.time down to the nearest 30 minutes interval, and round c.until up to the nearest interval. This way your where clause will have the correct range.
To do the rounding you will need to convert the times to datetime which you can do like so:
CAST(CONVERT(varchar,THE_TIME_AS_VARCHAR,121) AS datetime)
Then you can round down to the nearest 30 minutes like so:
DATEADD(mi, DATEDIFF(mi, 0, THE_TIME_AS_DATETIME)/30*30, 0)
And round up like so:
DATEADD(mi, DATEDIFF(mi, 30, THE_TIME_AS_DATETIME)/30*30, 0)
Applying all that to your existing code would give you this:
select t.time,
isnull(
(select c.studentCode
from tbclassrsv c
where c.transdate='2014-02-05 00:00:00'
and c.class='ROOM 01'
and c.status<>'DEL'
and t.time>= DATEADD(mi, DATEDIFF(mi, 0, CAST(CONVERT(varchar,c.time,121) AS datetime))/30*30, 0)
and t.time<= DATEADD(mi, DATEDIFF(mi, 30, CAST(CONVERT(varchar,c.until,121) AS datetime))/30*30, 0)
),'-') [Student]