I am Unable to insert date data and time data into oracle table. Please find the below query and error
INSERT INTO Sunday_Service (
Service_ID,
Service_date,
Start_time,
End_time,
Service_location,
No_of_children)
Values (
Seq_service_id.nextVal,
TO_DATE('YYYY-MM-DD', '2022-07-03'),
TO_DATE('hh24:mi:ss', '09:00:00'),
TO_DATE('hh24:mi:ss', '10:15:00'),
'RM 2101',
'10');
error:
Error report ORA-01821
You have your parameters switched in your TO_DATE function calls. Your TO_DATE function calls should look like this:
TO_DATE ('2022-07-03', 'YYYY-MM-DD'),
TO_DATE ('09:00:00', 'hh24:mi:ss'),
TO_DATE ('10:15:00', 'hh24:mi:ss')
You have the arguments to to_date() the wrong way around:
INSERT INTO Sunday_Service (Service_ID, Service_date,
Start_time, End_time,
Service_location, No_of_children)
VALUES (Seq_service_id.nextVal,
TO_DATE('2022-07-03', 'YYYY-MM-DD'),
TO_DATE('09:00:00', 'hh24:mi:ss'),
TO_DATE('10:15:00', 'hh24:mi:ss'),
'RM 2101',
'10');
But you probably want to combine the time and date, rather than holding them in separate columns; so if you removed service_date from your table you could do:
INSERT INTO Sunday_Service (Service_ID,
Start_time, End_time,
Service_location, No_of_children)
VALUES (Seq_service_id.nextVal,
TO_DATE('2022-07-03 09:00:00', 'YYYY-MM-DD HH24:MI:SS'),
TO_DATE('2022-07-03 10:15:00', 'YYYY-MM-DD HH24:MI:SS'),
'RM 2101',
'10');
Apart from anything else, that will make it possible to handle service calls that span midnight or multiple days.
You could also use timestamp literals:
...
VALUES (Seq_service_id.nextVal,
TIMESTAMP '2022-07-03 09:00:00',
TIMESTAMP '2022-07-03 10:15:00',
...
or slightly more explcitly:
...
VALUES (Seq_service_id.nextVal,
CAST(TIMESTAMP '2022-07-03 09:00:00' AS DATE),
CAST(TIMESTAMP '2022-07-03 10:15:00' AS DATE),
...
If no_of_children is a number column, as it appears, then the last value should be a number - 10 rather than '10'.
Related
TLDR;
What is the equivalent of the following Python code snippet in PostgreSQL?
df.groupby('column').apply(function)
Where df is a Pandas DataFrame instance.
Context
I am used to the Split-Apply-Combine Paradigm in Python and want to apply the same framework in PostgreSQL.
Suppose I have the following table with a time, place, and measurement:
CREATE TABLE IF NOT EXISTS test_table (place VARCHAR(10), time TIMESTAMP, measurement FLOAT);
TRUNCATE test_table;
INSERT INTO test_table
VALUES ('A', TO_TIMESTAMP('2022-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1.0),
('A', TO_TIMESTAMP('2022-01-01 00:15:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('A', TO_TIMESTAMP('2022-01-01 00:30:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('A', TO_TIMESTAMP('2022-01-01 00:45:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('A', TO_TIMESTAMP('2022-01-01 01:00:00', 'YYYY-MM-DD HH24:MI:SS'), 3.0),
('B', TO_TIMESTAMP('2022-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 3.0),
('B', TO_TIMESTAMP('2022-01-01 00:15:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('B', TO_TIMESTAMP('2022-01-01 00:30:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('B', TO_TIMESTAMP('2022-01-01 00:45:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('B', TO_TIMESTAMP('2022-01-01 01:00:00', 'YYYY-MM-DD HH24:MI:SS'), 3.0),
('C', TO_TIMESTAMP('2022-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 1.0),
('C', TO_TIMESTAMP('2022-01-01 00:15:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('C', TO_TIMESTAMP('2022-01-01 00:30:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('C', TO_TIMESTAMP('2022-01-01 00:45:00', 'YYYY-MM-DD HH24:MI:SS'), 2.0),
('C', TO_TIMESTAMP('2022-01-01 01:00:00', 'YYYY-MM-DD HH24:MI:SS'), 3.0);
Associated to each place is a timeseries. Sometimes the measurement device at a given place will flatline and my goal is to move the flatline rows to another table.
I have written the following query to get the table I want for a given place.
SELECT place, time, measurement
FROM (SELECT place, time, measurement, LEAD(measurement, 1) OVER (ORDER BY time) AS leading_measurement
FROM test_table WHERE place = 'A') q
WHERE NOT measurement = leading_measurement OR leading_measurement IS NULL;
Within the query I had a subquery with a clause WHERE place = 'A' because the cleaning algorithm would detect the last row of A as being the same as the first row of B and I would not want to remove that row. But this also means I have not "cleaned" the other two places.
In theory I would like to GROUP BY place run the query, and union the results. However the GROUP BY clause only supports aggregate functions and my query returns multiple rows. I want to somehow SELECT DISTINCT(place) and run a for loop over that list. The Python equivalent is:
test_table.groupby('place') \
.apply(lambda place:
place[place["measurement"].diff(1) != 0])
I can (and have) been using Python to export to CSV then import the CSV into PSQL tables but my boss would greatly appreciate it done in PostgreSQL.
I would appreciate any guidence, even a link to a relevant manual page.
Do not give up on SQL quite so quickly.
If I understand correctly you want to to copy to another table then delete those rows which have the same measurement by place and time. So for Place A move then delete the rows with times 00:30:00 and 00:40:00. This is because those are the same as time stamp 00:15:00. With similar copy and delete for Place B and Place C.
If this is correct then it is quite easily done in SQL, at least Postgres SQL. It can be done in a single statement. Postgres SQL permits DML operations is a CTE. This allows you write a CTE to identify the rows to process in the first table, then use that CTE to insert those rows onto the second table, and finally use the same CTE to delete from the first table. (See demo)
with to_move(rctid) as
( select ctid
from (select place, time, measurement
, lead(measurement, 1) over (partition by place order by time) as leading_measurement, ctid
from test_table
) q
where measurement = leading_measurement
)
, movers as
( insert into test_table_flat (place, time, measurement)
select t.place, t.time, t.measurement
from test_table t
where t.ctid in (select rctid from to_move)
)
delete
from test_table
where ctid in (select rctid from to_move) ;
I have a table where users perform an order action. I want to get difference in dates between his two or more orders. And similar for all users and then calculate their average or median.
Another issue is the order rows are duplicates because of another column in the table called order_received time which are 5 secs apart due to this two rows are created for the same users with same order time.
Based on your comment on my initial answer here is another worksheet.
Table DDL
create table tbl_order(
order_id integer,
account_number integer,
ordered_at date
);
Data as in other thread you pointed out
insert into tbl_order values (1, 1001, to_date('10-Sep-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (2, 2001, to_date('01-Sep-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (3, 2001, to_date('03-Sep-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (4, 1001, to_date('12-Sep-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (5, 3001, to_date('18-Sep-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (6, 1001, to_date('20-Sep-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS'));
Query
WITH VW AS (
SELECT ACCOUNT_NUMBER,
MIN(ORDERED_AT) EARLIEST_ORDER_AT,
MAX(ORDERED_AT) LATEST_ORDER_AT,
ROUND(MAX(ORDERED_AT) - MIN(ORDERED_AT), 5) DIFF_IN_DAYS,
COUNT(*) TOTAL_ORDER_COUNT
FROM TBL_ORDER
GROUP BY ACCOUNT_NUMBER
)
SELECT ACCOUNT_NUMBER, EARLIEST_ORDER_AT, LATEST_ORDER_AT,
DIFF_IN_DAYS, ROUND( DIFF_IN_DAYS/TOTAL_ORDER_COUNT, 4) AVERAGE
FROM VW;
Result
===========Initial answer hereafter===========
Your question is not entirely clear, for example
Do you want difference in date per day (a user can make multiple orders per day) or just between their earliest and latest orders
What do you mean by average is it just (latest order date - earliest order date) / total purchase? This will be hours / purchase. is it even useful?
Anyways, here is a working sheet, this will give enough to set you in right direction (hopefully). This is for Oracle database, will work mostly for other database except the time conversion functions used here. You will have to search and use equivalent functions for database of your choice, if its not Oracle.
Create table
create table tbl_order(
order_id integer,
user_id integer,
item varchar2(100),
ordered_at date
);
Insert some data
insert into tbl_order values (8, 1, 'A2Z', to_date('21-Mar-2019 16:30:20', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (1, 1, 'ABC', to_date('22-Mar-2019 07:30:20', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (2, 1, 'ABC', to_date('22-Mar-2019 07:30:20', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (3, 1, 'EFGT', to_date('22-Mar-2019 09:30:30', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (4, 1, 'XYZ', to_date('22-Mar-2019 12:38:50', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (5, 1, 'ABC', to_date('22-Mar-2019 16:30:20', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (6, 2, 'ABC', to_date('22-Mar-2019 14:20:20', 'DD-MON-YYYY HH24:MI:SS'));
insert into tbl_order values (7, 2, 'A2C', to_date('22-Mar-2019 14:20:50', 'DD-MON-YYYY HH24:MI:SS'));
Get latest, earliest and total_purchase per user and an average
WITH VW AS (
SELECT USER_ID,
TO_CHAR(MIN(ORDERED_AT), 'DD-MON-YYYY HH24:MI:SS') EARLIEST_ORDER_AT,
TO_CHAR(MAX(ORDERED_AT), 'DD-MON-YYYY HH24:MI:SS')LATEST_ORDER_AT,
ROUND(MAX(ORDERED_AT) - MIN(ORDERED_AT), 5) * 24 DIFF_IN_HOURS,
COUNT(*) TOTAL_ORDER_COUNT
FROM TBL_ORDER
GROUP BY USER_ID
)
SELECT USER_ID, EARLIEST_ORDER_AT, LATEST_ORDER_AT,
DIFF_IN_HOURS, DIFF_IN_HOURS/TOTAL_ORDER_COUNT AVERAGE
FROM VW;
Get latest, earliest and total_purchase per user per day and an average
WITH VW AS (
SELECT USER_ID, TO_CHAR(ORDERED_AT, 'DD-MON-YYYY') ORDER_DATE_PART,
TO_CHAR(MIN(ORDERED_AT), 'DD-MON-YYYY HH24:MI:SS') EARLIEST_ORDER_AT,
TO_CHAR(MAX(ORDERED_AT), 'DD-MON-YYYY HH24:MI:SS')LATEST_ORDER_AT,
ROUND(MAX(ORDERED_AT) - MIN(ORDERED_AT), 5) * 24 DIFF_IN_HOURS,
COUNT(*) TOTAL_ORDER_COUNT
FROM TBL_ORDER
GROUP BY USER_ID, TO_CHAR(ORDERED_AT, 'DD-MON-YYYY')
)
SELECT USER_ID, ORDER_DATE_PART, EARLIEST_ORDER_AT, LATEST_ORDER_AT,
DIFF_IN_HOURS, DIFF_IN_HOURS/TOTAL_ORDER_COUNT AVERAGE
FROM VW;
any help guys I got error column not allowed here for datetime !
INSERT INTO MEMBERS_CONTRIBUTIONS (
CONTRIBUTION_TYPE,
FROM_DATE,
TO_DATE,
ADDED_PERIOD_IN_MONTHS,
MEMBER_AMOUNT,
THE_CURRENCY,
MATURITY_DATE
) VALUES (
4,
convert(datetime, '6/1/2016 12:00:00 AM', 5),
convert(datetime, '6/1/2016 12:00:00 AM', 5),
0,
2500,
'OMR',
convert(datetime, '6/30/2016 12:00:00 AM', 5)
);
You are trying to use the SQL Server CONVERT() function in Oracle - the Oracle CONVERT() function converts from one character-set to another and does not do what you want.
Instead, you can use a date literal:
INSERT INTO MEMBERS_CONTRIBUTIONS (
CONTRIBUTION_TYPE,
FROM_DATE,
TO_DATE,
ADDED_PERIOD_IN_MONTHS,
MEMBER_AMOUNT,
THE_CURRENCY,
MATURITY_DATE
) VALUES (
4,
DATE '2016-06-01',
DATE '2016-06-01',
0,
2500,
'OMR',
DATE '2016-06-30'
);
In Oracle, all DATE types have both a date and time component - the date literal syntax will just set the time component to 00:00:00 (or 12:00:00 AM in a 12 hour clock).
Or if you want to specify the time component then you can use the timestamp literal (which Oracle will implicitly cast to a DATE type if that is the type of the column you are storing it in):
INSERT INTO MEMBERS_CONTRIBUTIONS (
CONTRIBUTION_TYPE,
FROM_DATE,
TO_DATE,
ADDED_PERIOD_IN_MONTHS,
MEMBER_AMOUNT,
THE_CURRENCY,
MATURITY_DATE
) VALUES (
4,
TIMESTAMP '2016-06-01 00:00:00',
TIMESTAMP '2016-06-01 00:00:00',
0,
2500,
'OMR',
TIMESTAMP '2016-06-30 00:00:00'
);
Or you could explicitly cast a string literal to a date using the TO_DATE() function:
INSERT INTO MEMBERS_CONTRIBUTIONS (
CONTRIBUTION_TYPE,
FROM_DATE,
TO_DATE,
ADDED_PERIOD_IN_MONTHS,
MEMBER_AMOUNT,
THE_CURRENCY,
MATURITY_DATE
) VALUES (
4,
TO_DATE( '6/1/2016 12:00:00 AM', 'MM/DD/YYYY HH12:MI:SS AM' ),
TO_DATE( '6/1/2016 12:00:00 AM', 'MM/DD/YYYY HH12:MI:SS AM' ),
0,
2500,
'OMR',
TO_DATE( '6/30/2016 12:00:00 AM', 'MM/DD/YYYY HH12:MI:SS AM' )
);
The expression convert(datetime, '6/1/2016 12:00:00 AM', 5) calls for a column with the name datetime. But your insert statement doesn't offer a context involving any columns at all, so the query parser can't make any sense of datetime. Hence your ORA-00948 error.
I guess you're trying to put a date/time constant, which from your example could mean either 1-Jun-2016 or 6-Jan-2016, into a date datatype. You need to use the TO_DATE() function to convert your strings to that format. I'm not going to suggest a particular form of the call, because I don't know exactly how your strings are formatted.
I have a company table with list of companies name and company id.
Now there is a Value table which hold information about the company with reference to company id.
I need to first get the list and size of the companies and for all the companies insert a particular feature information in the Value table.
This means I need to have all companies having those features in the Value table.
I tried to use the below SQL which gives a compilation error. But the for loop works well without the insert.
DECLARE
x NUMBER(2) ;
BEGIN
FOR x IN (select distinct company_num from company where comp_IN_comp='T') LOOP
INSERT INTO VALUE (PROPERTY_NUM, DATA_GROUP, NUM_UPDATES,
CREATED_DATE, CREATED_BY, LAST_UPDATED_DATE, LAST_UPDATED_BY, VALUE) VALUES
('78', x ,'0', TO_DATE('2015-12-17 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),
'ADMIN', TO_DATE('2015-12-17 00:00:00', 'YYYY-MM-DD HH24:MI:SS'), 'ADMIN', 'N');
END LOOP;
END;
You don't need a loop for this - just use an insert-select statement:
INSERT INTO VALUE (PROPERTY_NUM,
DATA_GROUP,
NUM_UPDATES,
CREATED_DATE,
CREATED_BY,
LAST_UPDATED_DATE,
LAST_UPDATED_BY,
VALUE)
SELECT DISTINCT '78',
company_num,
'0',
TO_DATE('2015-12-17 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),
'ADMIN',
TO_DATE('2015-12-17 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),
'ADMIN',
'N'
FROM company
WHERE comp_in_comp='T'
I have creater the table successfully as follows:
CREATE TABLE TOY_STORE
(
TOY_STORE_ID NUMBER(3) PRIMARY KEY,
TOY_STORE_NAME VARCHAR2(30) NOT NULL,
CITY VARCHAR2(30) DEFAULT 'Delhi',
PHONENUMBER NUMBER(10) NOT NULL UNIQUE,
STORE_OPENING_TIME TIMESTAMP,
STORE_CLOSING_TIME TIMESTAMP
);
ALTER TABLE TOY_STORE ADD CHECK (EXTRACT(HOUR FROM CAST (TO_CHAR (STORE_OPENING_TIME, 'YYYY-MON-DD HH24:MI:SS') AS TIMESTAMP)) > 8 || NULL);
ALTER TABLE TOY_STORE ADD CHECK (EXTRACT(HOUR FROM CAST(TO_CHAR(STORE_CLOSING_TIME, 'YYYY-MON-DD HH24:MI:SS') AS TIMESTAMP)) < 22 || NULL);
Now I want to enter data in the table. I executed the following command (here the second data is "Kid's Cave"),
INSERT INTO TOY_STORE VALUES(1, 'Kid''s Cave', 'Delhi', 9912312312, 2014-04-01 09:10:12, 2014-04-01 21:42:05);
But it showed the following error..
ORA-00917: missing comma
Please explain
You need to put the dates inside ''. Try this:
INSERT INTO TOY_STORE
VALUES(1, 'Kid''s Cave', 'Delhi', 9912312312, '2014-04-01 09:10:12', '2014-04-01 21:42:05');
On a side note:
I will suggest you to use varchar() to store PhoneNumbers instead of Number datatype
Dates don't have a single quote in your query - Use like so:
'2014-04-01 09:10:12', '2014-04-01 21:42:05'
The problem isn't the ', it's the fact that you are not quoting the date literals. Oracle interprets it as several integer literals with operators between them, and fails because there's no comma separating them.
Surrounding them by quotes (') should work:
INSERT INTO TOY_STORE VALUES
(1,
'Kid''s Cave',
'Delhi',
9912312312,
'2014-04-01 09:10:12',
'2014-04-01 21:42:05');
But it's a bad practice, as it assumes the format matches the database's default date format, which makes your code error prone and unprortable. A better approach would be to explicitly convert these values to timestamps with an explicitly stated format:
INSERT INTO TOY_STORE VALUES
(1,
'Kid''s Cave',
'Delhi',
9912312312,
TO_TIMESTAMP('2014-04-01 09:10:12', 'YYYY-MM-DD HH24:MI:SS'),
TO_TIMESTAMP('2014-04-01 21:42:05', 'YYYY-MM-DD HH24:MI:SS'));
Try using to_date to convert string into date
INSERT INTO TOY_STORE
VALUES (1, 'Kid''s Cave', 'Delhi', 9912312312,
to_date('2014-04-01 09:10:12', 'yyyy-mm-dd hh24:mi:ss'),
to_date('2014-04-01 21:42:05', 'yyyy-mm-dd hh24:mi:ss'));
you can also use TIMESTAMP literal
INSERT INTO TOY_STORE
VALUES (1, 'Kid''s Cave', 'Delhi', 9912312312,
TIMESTAMP '2014-04-01 09:10:12',
TIMESTAMP '2014-04-01 21:42:05');