I have a VARRAYS TYPE wanted to "flatten" the structure with the TABLE expression.
The example data
CREATE OR REPLACE TYPE ARIS.NUMBER_VARRAY_5 AS VARRAY (5) OF NUMBER NOT NULL;
CREATE TABLE ARIS.TEST_2
(
DATE_START DATE,
DATE_END DATE,
O3 ARIS.NUMBER_VARRAY_5,
CATEGORY NUMBER
)
SET DEFINE OFF;
Insert into TEST_2
(DATE_START, DATE_END, O3, CATEGORY)
Values
(TO_DATE('01/01/2005 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('01/05/2005 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), NUMBER_VARRAY_5(281.25,-9999,291.5,310.5,298.75), NULL);
Insert into TEST_2
(DATE_START, DATE_END, O3, CATEGORY)
Values
(TO_DATE('01/02/2005 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('01/06/2005 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), NUMBER_VARRAY_5(-9999,291.5,310.5,298.75,300.75), NULL);
COMMIT;
using the SQL statement
select O3.* from test_2 t, table(t.o3) O3
I can get the result
COLUMN_VALUE
281.25
-9999
291.5
310.5
298.75
-9999
291.5
310.5
298.75
300.75
The question is how I get the results like
DATE_START DATE_END 03.VALUE1 03.VALUE2 03.VALUE3 03.VALUE4 03.VALUE5
01/01/2005 01/05/2005 281.25 -9999 291.5 310.5 298.75
01/02/2005 01/06/2005 -9999 291.5 310.5 298.75 300.75
Try This,
SELECT
*
FROM
(
select
t.Date_start,
t.Date_end,
row_number() OVER ( PARTITION BY DATE_START, DATE_END
ORDER BY
ROWNUM) rn,
O3.*
from
test_2 t,
table(t.o3) O3
)
PIVOT ( MAX(column_value) FOR rn in
(
1 as "03.VALUE1",
2 as "03.VALUE2",
3 as "03.VALUE3",
4 as "03.VALUE4",
5 as "03.VALUE5"
)
) ;
Related
Best way to get high value of partition from oracle database?
"Best" is subjective but you can retrieve the high values by quering the data dictionary:
SELECT partition_name,
high_value
FROM USER_TAB_PARTITIONS
WHERE table_name = 'YOUR_TABLE_NAME';
One way is to use XML
create table t (
x date
) partition by range (x) (
partition p0 values less than (date'2015-01-01'),
partition p1 values less than (date'2015-06-01'),
partition pmax values less than (maxvalue)
);
with xml as (
select dbms_xmlgen.getxmltype('select table_name, partition_name, high_value from user_tab_partitions where table_name = ''T''') as x
from dual
)
select extractValue(rws.object_value, '/ROW/TABLE_NAME') table_name,
extractValue(rws.object_value, '/ROW/PARTITION_NAME') partition,
extractValue(rws.object_value, '/ROW/HIGH_VALUE') high_value
from xml x,
table(xmlsequence(extract(x.x, '/ROWSET/ROW'))) rws;
TABLE_NAME PARTITION HIGH_VALUE
---------- ---------- ------------------------------------------------------------------------------------------
T P0 TO_DATE(' 2015-01-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
T P1 TO_DATE(' 2015-06-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIAN')
T PMAX MAXVALUE
I am trying following query to insert data from a file. How do I calculate TOTAL_HOURS from in_date and out_date? I know we can not select them as "as in_date" and use it later. It was for illustration purpose only.
The script is reading data from a file and it is not stored in database yet.
insert into Table_A (
Id,
IN_DATE,
OUT_DATE,
TOTAL_HOURS,
)
values (
1,
'2021-10-04 07:00:00' as in_date,
'2021-10-04 07:00:00' as out_date,
DATEDIFF(second, out_date, in_date) / 3600.0
);
If you want to INSERT a static datetime using TIMESTAMPDIFF:
INSERT INTO Table_A (Id, IN_DATE, OUT_DATE, TOTAL_HOURS)
SELECT 1, '2021-10-04 07:00:00', '2021-10-04 08:00:00',
TIMESTAMPDIFF(HOUR, '2021-10-04 07:00:00', '2021-10-04 08:00:00')
If you want to INSERT a dynamic datetime using data from another table (i.e. Table_B to Table_A using a key):
INSERT INTO Table_A (Id, IN_DATE, OUT_DATE, TOTAL_HOURS)
SELECT Id, IN_DATE, OUT_DATE,
TIMESTAMPDIFF(HOUR, IN_DATE, OUT_DATE) FROM Table_B WHERE Id = 1
Result:
Id
IN_DATE
OUT_DATE
TOTAL_HOURS
1
2021-10-04 07:00:00
2021-10-04 08:00:00
1
Fiddle here.
To INSERT from a .csv file use the LOAD DATA INFILE command and add the TIMESTAMPDIFF calculation to the SET clause:
LOAD DATA INFILE 'c:/tmp/discounts_2.csv'
INTO TABLE Table_A
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS
(Id,#IN_DATE,#OUT_DATE)
SET IN_DATE=#IN_DATE,
OUT_DATE=#OUT_DATE,
TIMESTAMPDIFF(HOUR, #IN_DATE, #OUT_DATE);
I have a table with a Timestamp column which I need to filter after '2020-08-26', but every solution won't work
RUN_TIME
2020-07-22 04:22:07
2020-07-22 04:34:07
2020-07-22 04:45:07
2020-07-22 04:50:07
2020-07-22 04:55:08
I tried the below queries:
WHERE CAST (RUN_DATE AS DATE) >= TO_DATE('2020-08-26', 'yyyy-mm-dd')
WHERE to_date(RUN_DATE, 'YYYY-MM-DD hh24:mi:ss') >= to_date('26-08-2020 23:59:59', 'YYYY-MM-DD hh24:mi:ss')
WHERE RUN_DATE >= TO_TIMESTAMP('26-08-2020 23:59:59')
Use a TIMESTAMP literal:
SELECT *
FROM table_name
WHERE run_time >= TIMESTAMP '2020-08-27 00:00:00';
or, use a DATE literal:
SELECT *
FROM table_name
WHERE run_time >= DATE '2020-08-27';
or, use TO_TIMESTAMP with a format model:
SELECT *
FROM table_name
WHERE run_time >= TO_TIMESTAMP( '2020-08-27', 'YYYY-MM-DD' );
or, use TO_DATE with a format model:
SELECT *
FROM table_name
WHERE run_time >= TO_DATE( '2020-08-27', 'YYYY-MM-DD' );
Which for the sample data:
CREATE TABLE TABLE_NAME ( run_time TIMESTAMP(6) );
INSERT INTO table_name ( run_time )
SELECT TIMESTAMP '2020-07-22 04:22:07' FROM DUAL UNION ALL
SELECT TIMESTAMP '2020-07-22 04:34:07' FROM DUAL UNION ALL
SELECT TIMESTAMP '2020-07-22 04:45:07' FROM DUAL UNION ALL
SELECT TIMESTAMP '2020-07-22 04:50:07' FROM DUAL UNION ALL
SELECT TIMESTAMP '2020-07-22 04:55:08' FROM DUAL UNION ALL
SELECT TIMESTAMP '2020-08-26 23:59:59.999999' FROM DUAL UNION ALL
SELECT TIMESTAMP '2020-08-27 00:00:00' FROM DUAL;
All output:
| RUN_TIME |
| :------------------------ |
| 27-AUG-20 00.00.00.000000 |
db<>fiddle here
Just:
where run_date >= date '2020-08-26'
That's direct filtering against a date literal.
run_date is a timestamp already, so you should not attempt to convert it. Also, to_timestamp() takes a second argument, which specifies the format of the string; without it, it defaults to the nls_timestamp_format of your session (or database), which may not be what you expect
I want to make a query "If a record within that second and this sensor_id exists, update it with provided new value, else create a record with that value, sensor_id and time".
I managed to create this query:
DO
$do$
BEGIN
IF EXISTS (
SELECT
1
FROM
public.measurement_pm2_5
WHERE
measurement_time >= TO_TIMESTAMP('06.07.2016 23:28:43', 'DD.MM.YYYY HH24:MI:SS')
AND measurement_time < TO_TIMESTAMP('06.07.2016 23:28:44', 'DD.MM.YYYY HH24:MI:SS')
AND sensor_id = 2
) THEN UPDATE
public.measurement_pm2_5
SET
measurement_value = 27
WHERE
measurement_time >= TO_TIMESTAMP('06.07.2016 23:28:43', 'DD.MM.YYYY HH24:MI:SS')
AND measurement_time < TO_TIMESTAMP('06.07.2016 23:28:44', 'DD.MM.YYYY HH24:MI:SS')
AND sensor_id = 2;
ELSE INSERT
INTO
public.measurement_pm2_5
( sensor_id, measurement_time, measurement_value )
VALUES
( 2, TO_TIMESTAMP('06.07.2016 23:28:43', 'DD.MM.YYYY HH24:MI:SS'), 27 );
END IF;
END;
$do$
LANGUAGE plpgsql;
But it doesn't work as expected.
Query OK, 0 rows affected (execution time: 62 ms; total time: 62 ms)
Although this query:
SELECT
1
FROM
public.measurement_pm2_5
WHERE
measurement_time >= TO_TIMESTAMP('06.07.2016 23:28:43', 'DD.MM.YYYY HH24:MI:SS')
AND measurement_time < TO_TIMESTAMP('06.07.2016 23:28:44', 'DD.MM.YYYY HH24:MI:SS')
AND sensor_id = 2
returns one record, the UPDATE part of the first query doesn't look to be executed.
I'm using PostgreSQL 9.5.
What am I doing wrong?
Edit:
measurement_pm2_5 table:
CREATE TABLE public.measurement_pm2_5 (
sensor_id SERIAL,
measurement_time TIMESTAMP WITHOUT TIME ZONE NOT NULL,
measurement_value NUMERIC(6,2) NOT NULL,
CONSTRAINT measurement_pm2_5_sensor_id_fkey FOREIGN KEY (sensor_id)
REFERENCES public.sensor(id)
ON DELETE NO ACTION
ON UPDATE NO ACTION
NOT DEFERRABLE
)
WITH (oids = false);
From your SQL code it is easy to tell that you are experienced in procedural programming languages. PL/pgSQL requires a different mindset though. Carefully read the docs on PL/pgSQL programming and start thinking in sets and operations that succeed or fail. This is not at all meant to belittle you; take it as well-intended advice from a fellow programmer who has seen both sides of the fence.
In this case, simply try the UPDATE and if it fails, do an INSERT instead.
DO $do$
DECLARE
obs timestamp := to_timestamp('06.07.2016 23:28:43', 'DD.MM.YYYY HH24:MI:SS');
BEGIN
UPDATE public.measurement_pm2_5
SET measurement_value = 27
WHERE measurement_time = date_trunc('second', obs)
AND sensor_id = 2;
IF NOT FOUND THEN
INSERT INTO public.measurement_pm2_5
(sensor_id, measurement_time, measurement_value)
VALUES (2, obs, 27);
END IF;
END;
$do$ LANGUAGE plpgsql;
How can I do this:
select *
from tableName
where SESSION_START_DATE_TIME > To_Date ('12-Jan-2012 16:00', 'DD-MON-YYYY hh24:mi' )
SESSION_START_DATE_TIME is in the format '12/01/2012 13:16:32.000'
I tried where To_Date (SESSION_START_DATE_TIME, 'DD-MON-YYYY hh24:mi') > To_Date ('12-Jan-2012 16:00', 'DD-MON-YYYY hh24:mi' )
but no matter what I try I get the error:
SQL command not properly formed
In the example that you have provided there is nothing that would throw a SQL command not properly formed error. How are you executing this query? What are you not showing us?
This example script works fine:
create table tableName
(session_start_date_time DATE);
insert into tableName (session_start_date_time)
values (sysdate+1);
select * from tableName
where session_start_date_time > to_date('12-Jan-2012 16:00', 'DD-MON-YYYY hh24:mi');
As does this example:
create table tableName2
(session_start_date_time TIMESTAMP);
insert into tableName2 (session_start_date_time)
values (to_timestamp('01/12/2012 16:01:02.345678','mm/dd/yyyy hh24:mi:ss.ff'));
select * from tableName2
where session_start_date_time > to_date('12-Jan-2012 16:00', 'DD-MON-YYYY hh24:mi');
select * from tableName2
where session_start_date_time > to_timestamp('01/12/2012 14:01:02.345678','mm/dd/yyyy hh24:mi:ss.ff');
So there must be something else that is wrong.
If SESSION_START_DATE_TIME is of type TIMESTAMP you may want to try using the SQL function TO_TIMESTAMP. Here is an example:
SQL> CREATE TABLE t (ts TIMESTAMP);
Table created.
SQL> INSERT INTO t
2 VALUES (
3 TO_TIMESTAMP (
4 '1/12/2012 5:03:27.221008 PM'
5 ,'mm/dd/yyyy HH:MI:SS.FF AM'
6 )
7 );
1 row created.
SQL> SELECT *
2 FROM t
3 WHERE ts =
4 TO_TIMESTAMP (
5 '1/12/2012 5:03:27.221008 PM'
6 ,'mm/dd/yyyy HH:MI:SS.FF AM'
7 );
TS
-------------------------------------------------
12-JAN-12 05.03.27.221008 PM
Put it this way
where ("R"."TIME_STAMP">=TO_DATE ('03-02-2013 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
AND "R"."TIME_STAMP"<=TO_DATE ('09-02-2013 23:59:59', 'DD-MM-YYYY HH24:MI:SS'))
Where
R is table name.
TIME_STAMP is FieldName in Table R.
Try:
To_Date (SESSION_START_DATE_TIME, 'MM/DD/YYYY hh24:mi') >
To_Date ('12-Jan-2012 16:00', 'DD-MON-YYYY hh24:mi' )
Obviously '12/01/2012 13:16:32.000' doesn't match 'DD-MON-YYYY hh24:mi' format.
Update:
You need 'MM/DD/YYYY hh24:mi:ss.ff' format and to use TO_TIMESTAMP instead of TO_DATE cause dates don't hold millis in oracle.