Delete data before most recent Sunday - SQL Snowflake - sql

I need to delete all rows from before the most recent Sunday in a view. This can not be hard coded as the data gets updated daily. The only data I have is the date in dd-mm-yyyy format, and I have created a column with Day of Week (Monday being 1, Sunday being 7). Currently using SQL Snowflake, but any idea in any SQL types would be helpful.
TIA.

You can find the most recent Sunday by this formula:
DATE_TRUNC( 'week', current_date() ) - INTERVAL '1 DAY'
You do not need to store the day of the week as it can be easily fetched from the date. I think you store the dates in varchar as you said your dates in "dd-mm-yyyy format". I recommend you to store dates in DATE data type.
Here is a sample to delete the data before the most recent Sunday:
create or replace table test (mydate VARCHAR, dummy VARCHAR);
insert into test VALUES
('10-05-2021','willbedeleted'),
('30-10-2021','willbedeleted'),
('31-10-2021','shouldstay'), -- most recent sunday
('01-11-2021','shouldstay'),
('02-11-2021','shouldstay'),
('03-11-2021','shouldstay');
delete from test where TO_DATE( mydate, 'DD-MM-YYYY' ) <
DATE_TRUNC( 'week', current_date() ) - INTERVAL '1 DAY';
select * from test;
+------------+------------+
| MYDATE | DUMMY |
+------------+------------+
| 31-10-2021 | shouldstay |
| 01-11-2021 | shouldstay |
| 02-11-2021 | shouldstay |
| 03-11-2021 | shouldstay |
+------------+------------+

Related

Oracle SQL to delete the records except last 7 days/1 week

I am using Oracle SQL DB for ERP JD Edwards.
Dates are stored in Julian Format for this ERP.
We usually use this code to convert date from Julian to normal format.
decode(szupmj,0,' ',to_char(to_date(1900000 + olupmj,'YYYYDDD'),'MM/DD/YYYY'))
However we have a requirement where in, all data needs to be deleted except last 7 days.
Date column - 7
Please can someone help ?
SZEDUS
SZEDBT
SZUPMJ
ILPPO
74442
106108
ILPPO
74442
106108
ILPPO
77292
106109
You can convert your juliandate to a regular date and compare it to sysdate
Please test this first on a test database or use the dbfiddole to add rows with dates that are only a few days old
CREATE TABLE dates (
"SZEDUS" VARCHAR(5),
"SZEDBT" INTEGER,
"SZUPMJ" INTEGER
);
INSERT INTO dates
("SZEDUS", "SZEDBT", "SZUPMJ")
VALUES
('ILPPO', '74442', '106108');
INSERT INTO dates
("SZEDUS", "SZEDBT", "SZUPMJ")
VALUES
('ILPPO', '74442', '106108');
INSERT INTO dates
("SZEDUS", "SZEDBT", "SZUPMJ")
VALUES
('ILPPO', '77292', '106109');
SELECT * FROM dates
SZEDUS | SZEDBT | SZUPMJ
:----- | -----: | -----:
ILPPO | 74442 | 106108
ILPPO | 74442 | 106108
ILPPO | 77292 | 106109
DELETE FROM dates WHERE to_date(1900000 + SZUPMJ,'YYYYDDD') < trunc(sysdate) - 7
3 rows affected
SELECT * FROM dates
SZEDUS | SZEDBT | SZUPMJ
:----- | -----: | -----:
db<>fiddle here
Do this in a PL/SQL block where you can compute the date you want and compare withthat. It's much more efficient than applying a function to transform the Julian-formatted dates to Gregorian dates:
DECLARE
nCurr_date_minus_seven NUMBER := TO_NUMBER(TO_CHAR(SYSDATE - 7, 'YYYYDDD')) - 1900000;
BEGIN
DELETE FROM dates
WHERE SZUPMJ < nCurr_date_minus_seven;
END;
Use:
DELETE FROM table_name
WHERE szupmj < TO_CHAR(SYSDATE - INTERVAL '7' DAY, 'YYYYDDD') - 1900000;
(Which would be able to use an index on the szupmj column.)
db<>fiddle here

How to count the number of records based on the date and cycle is from Tuesday to Tuesday

CREATE TABLE rpt_tab (
e_id NUMBER(10),
region VARCHAR2(20),
stages VARCHAR2(20),
end_date DATE
);
INSERT INTO rpt_tab VALUES(11,'Mumbai','STG_1','12-04-22');
INSERT INTO rpt_tab VALUES(12,'France','STG_1','13-04-22');
INSERT INTO rpt_tab VALUES(13,'France','STG_1','14-04-22');
COMMIT;
I need to write a logic that will give me the data after finding the last Tuesday from the end_date column. I need a report with the logic as mentioned below:
If today is 12th April i.e SYSDATE and day is Tuesday then the report should give me only today's date data only.
If suppose the date is 13th April i.e tommorows date then the report should give me data count from 12th April(Tuesday) and 13th April.
Basically, the cycle will be from Tueday to Tuesday. If the date is 19th April (Tuesday) then the data count should be from 12th - 19th(Tuesday).
If the date is 19th April then again the cycle will be continued as mention in point no. 1 that will check if the sysdate is Tuesday and sysdate then it will give me the count.
My attempt:
WITH a AS(
SELECT COUNT(*) since_tuesday FROM rpt_tab
WHERE --end_date need to fetch the data count based on the end_date column and check Tuesday week day.
GROUP BY stages
)
SELECT since_tuesday FROM a;
Expected Output if date is 12th April (Tuesday):
+--------------+
| since_tuesday |
+--------------+
| 1 |
+--------------+
Expected Output if date is 13th April:
+--------------+
| since_tuesday |
+--------------+
| 2 |
+--------------+
Expected Output if date is 14th April:
+--------------+
| since_tuesday |
+--------------+
| 3 |
+--------------+
Need to check if sysdate is tuesday, then from there need to populate the count.
Rather than using language/territory specific functions like TO_CHAR or NEXT_DAY, you can do it independently of language and territory using TRUNC(SYSDATE - 1, 'IW') + 1 to shift the date back one day and then truncate it to the start of the ISO week (which is always a Monday) and then shift the day forward one day back to Tuesday:
SELECT COUNT(*) since_tuesday
FROM rpt_tab
WHERE end_date >= TRUNC(SYSDATE - 1, 'IW') + 1
AND end_date < TRUNC(SYSDATE) + 1
GROUP BY stages
Which, for the sample data outputs:
SINCE_TUESDAY
1
db<>fiddle here
You can use the NEXT_DAY() function for this:
WITH rpt_tab AS
(
SELECT 11 as e_id,'Mumbai' as region,'STG_1' as stages, TO_DATE('12-04-22','DD-MM-YY') as end_date FROM dual UNION ALL
SELECT 12,'France','STG_1',TO_DATE('13-04-22','DD-MM-YY') FROM dual UNION ALL
SELECT 13,'France','STG_1',TO_DATE('14-04-22','DD-MM-YY') FROM dual
)
SELECT COUNT(*)
FROM rpt_tab
WHERE end_date BETWEEN TRUNC(NEXT_DAY(end_date),'TUESDAY') - 7) AND TRUNC(NEXT_DAY(end_date),'TUESDAY'))
AND end_date <= TRUNC(SYSDATE);

Aggregate data based on unix time stamp crate database

I'm very new to SQL and time series database. I'm using crate database ( it think which is used PostgreSQL).i want to aggregate the data by hour,day ,week and month. Unix time stamp is used to store the data. following is my sample database.
|sensorid | reading | timestamp|
====================================
|1 | 1604192522 | 10 |
|1 | 1604192702 | 9.65 |
|2 | 1605783723 | 8.1 |
|2 | 1601514122 | 9.6 |
|2 | 1602292210 | 10 |
|2 | 1602291611 | 12 |
|2 | 1602291615 | 10 |
i tried the sql query using FROM_UNIXTIME not supported .
please help me?
im looking the answer for hourly data as follows.
sensorid ,reading , timestamp
1 19.65(10+9.65) 1604192400(starting hour unixt time)
2 8.1 1605783600(starting hour unix time)
2 9.6 1601514000(starting hour unix time)
2 32 (10+12+10) 1602291600(starting hour unix time)
im looking the answer for monthly data is like
sensorid , reading , timestamp
1 24.61(10+9.65+8.1) 1604192400(starting month unix time)
2 41.6(9.6+10+12+10) 1601510400(starting month unix time)
A straight-forward approach is:
SELECT
(date '1970-01-01' + unixtime * interval '1 second')::date as date,
extract(hour from date '1970-01-01' + unixtime * interval '1 second') AS hour,
count(c.user) AS count
FROM core c
GROUP BY 1,2
If you are content with having the date and time in the same column (which would seem more helpful to me), you can use date_trunc():
select
date_trunc('hour', date '1970-01-01' + unixtime * interval '1 second') as date_hour,
count(c.user) AS count
FROM core c
GROUP BY 1,2
You can convert a unix timestamp to a date/time value using to_timestamp(). You can aggregate along multiple dimensions at the same time using grouping sets. So, you might want:
select date_trunc('year', v.ts) as year,
date_trunc('month', v.ts) as month,
date_trunc('week', v.ts) as week,
date_trunc('day', v.ts) as day,
date_trunc('hour', v.ts) as hour,
count(*), avg(reading), sum(reading)
from t cross join lateral
(values (to_timestamp(timestamp))) v(ts)
group by grouping sets ( (year), (month), (week), (day), (hour) );

extract date only from given date in oracle sql

What is the best Oracle sql query to extract date?
input entry - 2020-10-14T07:26:32.661Z ,
expected output - 2020-10-14
If you want a DATE data type where the time component is midnight then:
SELECT TRUNC(
TO_TIMESTAMP_TZ(
'2020-10-14T07:26:32.661Z',
'YYYY-MM-DD"T"HH24:MI:SS.FF3TZR'
)
) AS truncated_date
FROM DUAL;
Which (depending on your NLS_DATE_FORMAT) outputs:
| TRUNCATED_DATE |
| :------------------ |
| 2020-10-14 00:00:00 |
(Note: a DATE data type has year, month, day, hour, minute and second components. Whatever client program you are using to access the database may choose not to show the time component but it will still be there.)
If you want a YYYY-MM-DD formatted string then:
SELECT TO_CHAR(
TO_TIMESTAMP_TZ(
'2020-10-14T07:26:32.661Z',
'YYYY-MM-DD"T"HH24:MI:SS.FF3TZR'
),
'YYYY-MM-DD'
) AS formatted_date
FROM DUAL;
| FORMATTED_DATE |
| :------------- |
| 2020-10-14 |
db<>fiddle here
The canonical way is probably trunc():
select trunc(input_entry)
This assumes that input_entry is a date or timestamp value.
EDIT:
If your input is just a string, use string operations:
select substr(input_entry, 1, 10)
You can also readily cast this to a date.

PostgreSql: select only weekends

I have a table containing the public holidays
id | description | date
1 | Ferragosto and Assunzione | 2012-08-15 00:00:00
2 | Tutti i santi (Ognissanti) | 2012-11-01 00:00:00
......
I want to select only the holidays occurring on the weekends (Saturday & Sunday) with PostgreSQL.
I know there is a function called extract and isodow to extract the day of week but I don't know how to use it in my case:
select extract(isodow from date '2016-12-12')
You could use query which is similar to this one:
SELECT *
FROM table
WHERE EXTRACT(ISODOW FROM date) IN (6, 7)