Query joined partitioned tables - oracle

I have 2 partitioned tables . I want to left joined them it means that i want all record of table 'A' that is in specific date , and data in table 'B' if there is any matched record (also in specific date). both tables are partitioned so i use partitioned column (time) in where clause , but in this query when there is not any matched record in table 'B' , the condition 'B.time' become null and the records of table 'A' dose not appear in result.
if I do not use time condition for table 'B', the execution plan of it become partition range all and has bad performance .
how can i edit the query?
select * from A left outer join B SSRESP
on A.ID = B.A_ID where
A.time >= to_date('1396/09/26 00:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and A.time <= to_date('1396/10/27 11:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and B.time >=
to_date('1396/09/26 00:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and B.time <=
to_date('1396/10/27 11:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')

There are 2 possibilities.
1) Move the condition to the on-clause:
select *
from A
left outer join B
on A.ID = B.A_ID
and B.time >= to_date('1396/09/26 00:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and B.time <= to_date('1396/10/27 11:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
where A.time >= to_date('1396/09/26 00:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and A.time <= to_date('1396/10/27 11:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
2) Filter the table before the left join:
select *
from A
left outer join
(SELECT * FROM B
WHERE B.time >= to_date('1396/09/26 00:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and B.time <= to_date('1396/10/27 11:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')) AS B
on A.ID = B.A_ID
where A.time >= to_date('1396/09/26 00:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')
and A.time <= to_date('1396/10/27 11:00:00',
'yyyy/mm/dd hh24:mi:ss',
'NLS_CALENDAR=persian')

Related

Possible to modify an existing partitioned Oracle table to utilize INTERVAL? [duplicate]

I have a table which is partitioned as below and has millions of rows of data. Table size is 120 GB.
PARTITION BY RANGE (Read_time) INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
Now I want to change to this partitioning strategy with existing data and future data. Table is inserted daily by job.
PARTITION BY RANGE (Read_time) INTERVAL(NUMTODSINTERVAL(1, 'DAY'))
I have 12 month partition (Oct'18 to Nov'19). I want partition to be converted to daywise.
For example: For Jul'19 partition, it should to be splitted to
01 Jul'19,
02 Jul'19
.......
31 Jul'19.
Data should also be moved to new partition
I tried split partition. New partition got created day wise , but rows didn't move to new partition.
To change for monthly interval to daily is a simple as
ALTER TABLE test SET INTERVAL (NUMTODSINTERVAL(1,'DAY'));
see the documentation for further details
Lets illustrate in on a small example
create table test
(dt date)
PARTITION BY RANGE (dt)
INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
(
PARTITION part_01 values LESS THAN (TO_DATE('01-01-2019','DD-MM-YYYY'))
);
insert into test (dt)
select date'2019-01-01' + rownum dt from dual
connect by level <= 100;
The table in montly intrval partitioned and contains 100 days of data - yielding in one initial partition and 4 new montly partition.
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
PART_01 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93334 TO_DATE(' 2019-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93335 TO_DATE(' 2019-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93336 TO_DATE(' 2019-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93337 TO_DATE(' 2019-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
Now we switch to daily partitioning
ALTER TABLE test SET INTERVAL (NUMTODSINTERVAL(1,'DAY'));
This makes nothing with existing data (so it is instant operation), also the new data for the current month will go in the current (month) partition.
The data loaded for the new month will be partitioned on daily basis.
Lets insert few new days
insert into test (dt)
select date'2019-01-01' + 100 +rownum dt from dual
connect by level <= 22;
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
PART_01 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93334 TO_DATE(' 2019-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93335 TO_DATE(' 2019-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93336 TO_DATE(' 2019-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93337 TO_DATE(' 2019-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93338 TO_DATE(' 2019-05-02 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93339 TO_DATE(' 2019-05-03 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93340 TO_DATE(' 2019-05-04 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
As expected starting with May the data are daily partitioned.
If you need also to re-partitioned your historical data, this will require reorganisation (data movement - will take some time for 120GB) using split partition.
alter table test
SPLIT PARTITION FOR(TO_DATE('2019-02-01','yyyy-mm-dd'))
AT (TO_DATE('2019-02-27','yyyy-mm-dd'));
alter table test
SPLIT PARTITION FOR(TO_DATE('2019-02-01','yyyy-mm-dd'))
AT (TO_DATE('2019-02-26','yyyy-mm-dd'));
This splits the last day in a new partition, you'll have to do it for each day in each monthly partition.
After this step also the history data is partitioned per day:
select * from test partition for ( DATE'2019-02-26');
DT
-------------------
26.02.2019 00:00:00

How to move data from partitioned table to another partitioned table

I have two monthly interval partitioned tables table1 and table2. Table1 is history table which holds historic data and table2 holds latest/live 6 months data. Every month I need to add or move the oldest partition from table2 to the history table table1.
Here is how to do it with no movement of data, just dictionary operations as Hermann has suggested.
T1 is my current 6 months, and T2 is history
SQL> create table t1
2 partition by range (x)
3 interval ( numtoyminterval(1,'MONTH') )
4 ( partition p1 values less than ( date '2021-01-01') )
5 as
6 select date '2021-01-01'+rownum x,
7 rownum y
8 from dual
9 connect by level <= 180;
Table created.
SQL>
SQL> create table t2
2 partition by range (x)
3 interval ( numtoyminterval(1,'MONTH') )
4 ( partition p1 values less than ( date '2015-01-01') )
5 as
6 select date '2021-01-01'-rownum x,
7 rownum y
8 from dual
9 connect by level <= 1000;
Table created.
SQL>
SQL> select partition_name, high_value
2 from user_tab_partitions
3 where table_name = 'T1';
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
P1 TO_DATE(' 2021-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22038 TO_DATE(' 2021-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22039 TO_DATE(' 2021-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22040 TO_DATE(' 2021-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22041 TO_DATE(' 2021-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22042 TO_DATE(' 2021-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22043 TO_DATE(' 2021-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
7 rows selected.
SQL>
SQL> select partition_name, high_value
2 from user_tab_partitions
3 where table_name = 'T2';
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
P1 TO_DATE(' 2015-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22044 TO_DATE(' 2021-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22045 TO_DATE(' 2020-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22046 TO_DATE(' 2020-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22047 TO_DATE(' 2020-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22048 TO_DATE(' 2020-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22049 TO_DATE(' 2020-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22050 TO_DATE(' 2020-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22051 TO_DATE(' 2020-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22052 TO_DATE(' 2020-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22053 TO_DATE(' 2020-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22054 TO_DATE(' 2020-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22055 TO_DATE(' 2020-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22056 TO_DATE(' 2020-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22057 TO_DATE(' 2019-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22058 TO_DATE(' 2019-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22059 TO_DATE(' 2019-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22060 TO_DATE(' 2019-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22061 TO_DATE(' 2019-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22062 TO_DATE(' 2019-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22063 TO_DATE(' 2019-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22064 TO_DATE(' 2019-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22065 TO_DATE(' 2019-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22066 TO_DATE(' 2019-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22067 TO_DATE(' 2019-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22068 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22069 TO_DATE(' 2018-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22070 TO_DATE(' 2018-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22071 TO_DATE(' 2018-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22072 TO_DATE(' 2018-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22073 TO_DATE(' 2018-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22074 TO_DATE(' 2018-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22075 TO_DATE(' 2018-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22076 TO_DATE(' 2018-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
34 rows selected.
To do a table exchange, you need to create a template table first, ie, you need something to exchange with
SQL>
SQL> create table exc
2 for exchange with table t1;
Table created.
Now I take the partition I want to remove from T1, and exchange it with EXC
SQL>
SQL> alter table t1 exchange partition for ( date '2021-01-15' ) with table exc;
Table altered.
Now I want to exchange it "into" T2, but I need a partition in T2 into which I can do the exchange. That partition does not exist yet, because it doesn't contain any of the 6 months in the current data. Thus we need to create an empty one. A simple trick to do that is the lock the non-existent partition, which will have the effect of creating one.
SQL>
SQL> lock table t2 partition for ( date '2021-01-15' ) in exclusive mode;
Table(s) Locked.
SQL>
SQL> select partition_name, high_value
2 from user_tab_partitions
3 where table_name = 'T2';
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
P1 TO_DATE(' 2015-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22044 TO_DATE(' 2021-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22045 TO_DATE(' 2020-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22046 TO_DATE(' 2020-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22047 TO_DATE(' 2020-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22048 TO_DATE(' 2020-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22049 TO_DATE(' 2020-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22050 TO_DATE(' 2020-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22051 TO_DATE(' 2020-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22052 TO_DATE(' 2020-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22053 TO_DATE(' 2020-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22054 TO_DATE(' 2020-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22055 TO_DATE(' 2020-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22056 TO_DATE(' 2020-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22057 TO_DATE(' 2019-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22058 TO_DATE(' 2019-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22059 TO_DATE(' 2019-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22060 TO_DATE(' 2019-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22061 TO_DATE(' 2019-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22062 TO_DATE(' 2019-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22063 TO_DATE(' 2019-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22064 TO_DATE(' 2019-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22065 TO_DATE(' 2019-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22066 TO_DATE(' 2019-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22067 TO_DATE(' 2019-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22068 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22069 TO_DATE(' 2018-12-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22070 TO_DATE(' 2018-11-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22071 TO_DATE(' 2018-10-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22072 TO_DATE(' 2018-09-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22073 TO_DATE(' 2018-08-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22074 TO_DATE(' 2018-07-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22075 TO_DATE(' 2018-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22076 TO_DATE(' 2018-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
SYS_P22077 TO_DATE(' 2021-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS',
35 rows selected.
Notice that we gained a new partition (which is empty). Now I exchange the EXC table (which has 1 month of data) with the empty partition.
SQL>
SQL> alter table t2 exchange partition for ( date '2021-01-15' ) with table exc;
Table altered.
SQL>
and we are done. Notice that we never needed to reference any of the interval partitions by name, we just used the FOR option in order to avoid that.

Can i change range interval partition from month to day in oracle

I have a table which is partitioned as below and has millions of rows of data. Table size is 120 GB.
PARTITION BY RANGE (Read_time) INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
Now I want to change to this partitioning strategy with existing data and future data. Table is inserted daily by job.
PARTITION BY RANGE (Read_time) INTERVAL(NUMTODSINTERVAL(1, 'DAY'))
I have 12 month partition (Oct'18 to Nov'19). I want partition to be converted to daywise.
For example: For Jul'19 partition, it should to be splitted to
01 Jul'19,
02 Jul'19
.......
31 Jul'19.
Data should also be moved to new partition
I tried split partition. New partition got created day wise , but rows didn't move to new partition.
To change for monthly interval to daily is a simple as
ALTER TABLE test SET INTERVAL (NUMTODSINTERVAL(1,'DAY'));
see the documentation for further details
Lets illustrate in on a small example
create table test
(dt date)
PARTITION BY RANGE (dt)
INTERVAL (NUMTOYMINTERVAL(1,'MONTH'))
(
PARTITION part_01 values LESS THAN (TO_DATE('01-01-2019','DD-MM-YYYY'))
);
insert into test (dt)
select date'2019-01-01' + rownum dt from dual
connect by level <= 100;
The table in montly intrval partitioned and contains 100 days of data - yielding in one initial partition and 4 new montly partition.
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
PART_01 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93334 TO_DATE(' 2019-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93335 TO_DATE(' 2019-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93336 TO_DATE(' 2019-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93337 TO_DATE(' 2019-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
Now we switch to daily partitioning
ALTER TABLE test SET INTERVAL (NUMTODSINTERVAL(1,'DAY'));
This makes nothing with existing data (so it is instant operation), also the new data for the current month will go in the current (month) partition.
The data loaded for the new month will be partitioned on daily basis.
Lets insert few new days
insert into test (dt)
select date'2019-01-01' + 100 +rownum dt from dual
connect by level <= 22;
PARTITION_NAME HIGH_VALUE
------------------------------ --------------------------------------------------------------------------------
PART_01 TO_DATE(' 2019-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93334 TO_DATE(' 2019-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93335 TO_DATE(' 2019-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93336 TO_DATE(' 2019-04-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93337 TO_DATE(' 2019-05-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93338 TO_DATE(' 2019-05-02 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93339 TO_DATE(' 2019-05-03 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
SYS_P93340 TO_DATE(' 2019-05-04 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA
As expected starting with May the data are daily partitioned.
If you need also to re-partitioned your historical data, this will require reorganisation (data movement - will take some time for 120GB) using split partition.
alter table test
SPLIT PARTITION FOR(TO_DATE('2019-02-01','yyyy-mm-dd'))
AT (TO_DATE('2019-02-27','yyyy-mm-dd'));
alter table test
SPLIT PARTITION FOR(TO_DATE('2019-02-01','yyyy-mm-dd'))
AT (TO_DATE('2019-02-26','yyyy-mm-dd'));
This splits the last day in a new partition, you'll have to do it for each day in each monthly partition.
After this step also the history data is partitioned per day:
select * from test partition for ( DATE'2019-02-26');
DT
-------------------
26.02.2019 00:00:00

Want to round the data

My Query is :
SELECT TO_CHAR((to_date('01-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS')+ (level-1)),'DD-MM-YYYY'),
TO_CHAR(to_date('01-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS') + level,'DD-MM-YYYY') ,
to_number(regexp_substr('7000 T', '^\d+'))/(TO_DATE('04-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS') - TO_DATE('01-01-2018 00:00', 'DD-MM-YYYY HH24:MI:SS'))
|| regexp_substr('7000 T', '[A-Z]') AS IP_PLAN
FROM dual
CONNECT BY level <= to_date('04-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS')-to_date('01-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS');
I want IP_PLAN like: 2333 T
ROUND(('7000 T'), '[A-Z]') is trying to round a string value, i.e. the T that is extracted from that source string, which doesn't make sense.
You need to round the number you generated just before that:
select to_char(to_date('01-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS') + level - 1,
'DD-MM-YYYY'),
to_char(to_date('01-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS') + level,
'DD-MM-YYYY') ,
round(
to_number(regexp_substr('7000 T', '^[[:digit:]]+'))
/ (to_date('04-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
- to_date('01-01-2018 00:00', 'DD-MM-YYYY HH24:MI:SS'))
)
|| regexp_substr('7000 T', '[^[:digit:]]*$') as ip_plan_consumption
from dual
connect by level <= to_date('04-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
- to_date('01-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS');
TO_CHAR(TO TO_CHAR(TO IP_PLAN_CONSUMPTION
---------- ---------- ------------------------------------------
01-01-2018 02-01-2018 2333 T
02-01-2018 03-01-2018 2333 T
03-01-2018 04-01-2018 2333 T
so you're doing
round(<number extracted by regex> / <difference in days >)
which is
round(7000 / 3) => round(2333.333...) => 2333
and then appending the T after wards.
I've changed the regex patterns slightly so it picks up the space ans any characters at the end. That's making some assumptions about possible values in that string though - i.e. that it's always one number followed by one non-numeric section.
Incidentally, if you're using fixed dates then it's simpler to use date literals:
select to_char(date '2018-01-01' + level - 1, 'DD-MM-YYYY'),
to_char(date '2018-01-01' + level, 'DD-MM-YYYY') ,
round(
to_number(regexp_substr('7000 T', '^[[:digit:]]+'))
/ (date '2018-01-04' - date '2018-01-01')
)
|| regexp_substr('7000 T', '[^[:digit:]]*$') as ip_plan_consumption
from dual
connect by level <= date '2018-01-04' - date '2018-01-01';
though I imagine the 7000 T and the date values are all being passed in as string in your real code so they need to be converted. You could use a CTE to only convert them once though, instead of repeatedly as you loop round.
SELECT TO_CHAR((to_date('01-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS')+ (level-1)),'DD-MM-YYYY'),
TO_CHAR(to_date('01-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS') + level,'DD-MM-YYYY') ,
round(to_number(regexp_substr('7000 T', '^\d+'))/(TO_DATE('04-01-2018 00:00:00', 'DD-MM-YYYY HH24:MI:SS') - TO_DATE('01-01-2018 00:00', 'DD-MM-YYYY HH24:MI:SS')),0)
AS IP_PLAN_CONSUMPTION
FROM dual
CONNECT BY level <= to_date('04-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS')-to_date('01-01-2018 00:00:00','DD-MM-YYYY HH24:MI:SS');
you have to use T in some other column;

Query transactions that occured only at a certain time

I am trying to run a select query that will pull all meds scheduled at 2300 for a date range. Is there a way I can convert the scheduled date/time to just hour? This is what I have so far:
SELECT DISTINCT USERCODE,
TRANSACTIONID,
ACTION,
TRANSACTIONHOUR,
SOURCE,
RXNUMBER,
DESCRIPTION,
MASTERPATIENTID,
FACILITYCODE,
ADMINISTRATIONTIME
FROM ( ABC.TL TL
INNER JOIN
ABC.S_VIEW S_VIEW
ON (TL.RXNUMBER = S_VIEW.RXNUMBER))
INNER JOIN
ABC.PV PATIENTVISIT
ON (TL.MASTERPATIENTID = PV.MASTERPATIENTID)
WHERE (TL.USERCODE NOT IN ('ABC'))
AND (TL.ACTION IN ('A', 'DC'))
AND (TL.TRANSACTIONHOUR BETWEEN to_date('2011-07-01 00:00:00', 'yyyy/mm/dd hh24:mi:ss') AND to_date('2011-09-30 23:59:59', 'yyyy/mm/dd hh24:mi:ss')
I would like the query to include all dispense during the specified dates but only at 2300 time. Database is oracle 10g.
First, you have given the date string in a different format and the format in different format. Make it consistent.
Try this:
SELECT DISTINCT USERCODE,
TRANSACTIONID,
ACTION,
TRANSACTIONHOUR,
SOURCE,
RXNUMBER,
DESCRIPTION,
MASTERPATIENTID,
FACILITYCODE,
ADMINISTRATIONTIME
FROM ( ABC.TL TL
INNER JOIN
ABC.S_VIEW S_VIEW
ON (TL.RXNUMBER = S_VIEW.RXNUMBER))
INNER JOIN
ABC.PV PATIENTVISIT
ON (TL.MASTERPATIENTID = PV.MASTERPATIENTID)
WHERE (TL.USERCODE NOT IN ('ABC'))
AND (TL.ACTION IN ('A', 'DC'))
AND (TL.TRANSACTIONHOUR BETWEEN to_date('2011/07/01 00:00:00', 'yyyy/mm/dd hh24:mi:ss') AND to_date('2011/09/30 23:59:59', 'yyyy/mm/dd hh24:mi:ss')
AND TO_CHAR(TL.TRANSACTIONHOUR, 'HH24MI') = '2300' --THIS IS THE NEW CONDITION

Resources