I need to convert Teradata SQL to GCP BQ SQL
DATE_ADD(DATE_ADD(CAST(CURRENT_DATE/100*100+1 AS DATE),INTERVAL 1 MONTH),INTERVAL -4 MONTH)
AND DATE_ADD(CAST(CURRENT_DATE/100*100+1 AS DATE),INTERVAL 1 MONTH) - 1)
I am getting following error message
No matching signature for operator / for argument types: DATE, INT64. Supported signatures: FLOAT64 / FLOAT64; NUMERIC / NUMERIC; BIGNUMERIC / BIGNUMERIC;
Here is the solution
select
date_add(date_add(date_add(date_add(date_add(DATE '1900-01-01', interval div(div((extract(YEAR from current_date()) - 1900) * 10000 + extract(MONTH from current_date()) * 100 + extract(DAY from current_date()), 100) * 100 + 1, 10000) YEAR), interval div(mod(div((extract(YEAR from current_date()) - 1900) * 10000 + extract(MONTH from current_date()) * 100 + extract(DAY from current_date()), 100) * 100 + 1, 10000), 100) - 1 MONTH), interval mod(div((extract(YEAR from current_date()) - 1900) * 10000 + extract(MONTH from current_date()) * 100 + extract(DAY from current_date()), 100) * 100 + 1, 100) - 1 DAY), interval 1 MONTH), interval -4 MONTH) add_4_month,
---
date_sub(date_add(date_add(date_add(date_add(DATE '1900-01-01', interval div(div((extract(YEAR from current_date()) - 1900) * 10000 + extract(MONTH from current_date()) * 100 + extract(DAY from current_date()), 100) * 100 + 1, 10000) YEAR), interval div(mod(div((extract(YEAR from current_date()) - 1900) * 10000 + extract(MONTH from current_date()) * 100 + extract(DAY from current_date()), 100) * 100 + 1, 10000), 100) - 1 MONTH), interval mod(div((extract(YEAR from current_date()) - 1900) * 10000 + extract(MONTH from current_date()) * 100 + extract(DAY from current_date()), 100) * 100 + 1, 100) - 1 DAY), interval 1 MONTH), interval 1 DAY) sub_1_month
Related
I need to group by Hour for converted epoch time, here is what I have done but it is still grouping by the day. Can anyone support?
select count (*) as "Total",to_char(trunc(to_date('19700101 00', 'YYYYMMDD HH24') + ( 1 / 24 / 60 / 60 ) * INSERTION_TIME),'DD/MM/YYYY HH24') as "Day"
from Records
where ID=35 and (INSERTION_TIME/86400)+ to_date('01-01-1970 00:00:00','dd-mm-yyyy HH24:MI:SS') >=sysdate - 4
group by trunc(to_date('19700101 00', 'YYYYMMDD HH24') + ( 1 / 24 / 60 / 60 ) * INSERTION_TIME)
order by trunc(to_date('19700101 00', 'YYYYMMDD HH24') + ( 1 / 24 / 60 / 60 ) * INSERTION_TIME)
You can get rid of most of the arithmetic and just use:
SELECT COUNT(*) as "Total",
TO_CHAR(
TRUNC(DATE '1970-01-01' + INTERVAL '1' SECOND * INSERTION_TIME, 'HH'),
'DD/MM/YYYY HH24'
) as "Day"
FROM Records
WHERE ID=35
AND DATE '1970-01-01' + INTERVAL '1' SECOND * INSERTION_TIME >=sysdate - 4
GROUP BY
TRUNC(DATE '1970-01-01' + INTERVAL '1' SECOND * INSERTION_TIME, 'HH')
ORDER BY
TRUNC(DATE '1970-01-01' + INTERVAL '1' SECOND * INSERTION_TIME, 'HH')
Note: Epoch time is usually 1970-01-01 00:00:00 UTC. If your session time zone is not UTC then you may be calculating the epoch time incorrectly and would want to use timestamps instead:
SELECT COUNT(*) as "Total",
TO_CHAR(
TRUNC(
TIMESTAMP '1970-01-01 00:00:00 UTC' + INTERVAL '1' SECOND * INSERTION_TIME,
'HH'
),
'DD/MM/YYYY HH24'
) as "Day"
FROM Records
WHERE ID=35
AND TIMESTAMP '1970-01-01 00:00:00 UTC' + INTERVAL '1' SECOND * INSERTION_TIME
>=SYSTIMESTAMP - INTERVAL '4' DAY
GROUP BY
TRUNC(
TIMESTAMP '1970-01-01 00:00:00 UTC' + INTERVAL '1' SECOND * INSERTION_TIME,
'HH'
)
ORDER BY
TRUNC(
TIMESTAMP '1970-01-01 00:00:00 UTC' + INTERVAL '1' SECOND * INSERTION_TIME,
'HH'
)
Notice the behavior of trunc on your expression. It removes the hour component.
Test case with dbfiddle.uk:
Test case
The ungrouped SQL, with extra expression in select list:
select to_char(trunc(to_date('19700101 00', 'YYYYMMDD HH24') + ( 1 / 24 / 60 / 60 ) * INSERTION_TIME),'DD/MM/YYYY HH24') as "Day"
, to_char( (to_date('19700101 00', 'YYYYMMDD HH24') + ( 1 / 24 / 60 / 60 ) * INSERTION_TIME),'DD/MM/YYYY HH24') as "Day"
from Records
where ID = 35 and (INSERTION_TIME/86400) + to_date('01-01-1970 00:00:00','dd-mm-yyyy HH24:MI:SS') >= sysdate - 4
AND rownum < 6
order by (to_date('19700101 00', 'YYYYMMDD HH24') + ( 1 / 24 / 60 / 60 ) * INSERTION_TIME)
;
The ungrouped result:
Now add the GROUP BY:
select COUNT(*) AS n
, to_char(trunc(to_date('19700101 00', 'YYYYMMDD HH24') + ( 1 / 24 / 60 / 60 ) * INSERTION_TIME),'DD/MM/YYYY HH24') as "Day"
, to_char( (to_date('19700101 00', 'YYYYMMDD HH24') + ( 1 / 24 / 60 / 60 ) * INSERTION_TIME),'DD/MM/YYYY HH24') as "Day"
from Records
where ID = 35 and (INSERTION_TIME/86400) + to_date('01-01-1970 00:00:00','dd-mm-yyyy HH24:MI:SS') >= sysdate - 4
group by (to_date('19700101 00', 'YYYYMMDD HH24') + ( 1 / 24 / 60 / 60 ) * INSERTION_TIME)
order by (to_date('19700101 00', 'YYYYMMDD HH24') + ( 1 / 24 / 60 / 60 ) * INSERTION_TIME)
;
The grouped result:
To create a test case:
CREATE TABLE Records (
id int
, insertion_time int
);
INSERT INTO Records VALUES (35, 4011134567);
INSERT INTO Records VALUES (35, 4011134567);
INSERT INTO Records VALUES (35, 4011134567);
INSERT INTO Records VALUES (35, 4011134567);
Does anyone have a easy solution to make a numbering from sunday to saturday and generate the dates in PostgreSQL(version 11).I have the below solution but it is limited to only 5 weeks and i need something that is flexible.
I have dates as a column in my source table, i want those dates to be numbered from saturday to sunday like below.
Current Query
WITH CTE AS
(
SELECT 1 as rno,generate_series( date_trunc('week', current_date)::date - 1
, date_trunc('week', current_date)::date + 5
, interval '1 day') current_week
)
,CTE_1 AS
(
SELECT rno,current_week FROM CTE
UNION
select 2,dt::date d from generate_series( (SELECT MIN(current_week)::DATE FROM CTE)- interval '7 days', (SELECT MIN(current_week)::DATE FROM CTE)- interval '1 days', interval '1 days') dt
)
,CTE_2 AS
(
SELECT rno,current_week FROM CTE_1
UNION
select 3,dt::date d from generate_series( (SELECT MIN(current_week)::DATE FROM CTE_1)- interval '7 days', (SELECT MIN(current_week)::DATE FROM CTE_1)- interval '1 days', interval '1 days') dt
)
,CTE_3 AS
(
SELECT rno,current_week FROM CTE_2
UNION
select 4,dt::date d from generate_series( (SELECT MIN(current_week)::DATE FROM CTE_2)- interval '7 days', (SELECT MIN(current_week)::DATE FROM CTE_2)- interval '1 days', interval '1 days') dt
)
,last_5_weeks as
(
SELECT rno,current_week FROM CTE_3
UNION
select 5,dt::date d from generate_series( (SELECT MIN(current_week)::DATE FROM CTE_3)- interval '7 days', (SELECT MIN(current_week)::DATE FROM CTE_3)- interval '1 days', interval '1 days') dt
)
SELECT rno,current_week::DATE as selected_date FROM last_5_weeks order by selected_date DESC
Current output
rno Date
1 "2020-10-24"
1 "2020-10-23"
1 "2020-10-22"
1 "2020-10-21"
1 "2020-10-20"
1 "2020-10-19"
1 "2020-10-18"
2 "2020-10-17"
2 "2020-10-16"
2 "2020-10-15"
2 "2020-10-14"
2 "2020-10-13"
2 "2020-10-12"
2 "2020-10-11"
3 "2020-10-10"
3 "2020-10-09"
3 "2020-10-08"
3 "2020-10-07"
3 "2020-10-06"
3 "2020-10-05"
3 "2020-10-04"
4 "2020-10-03"
4 "2020-10-02"
4 "2020-10-01"
4 "2020-09-30"
4 "2020-09-29"
4 "2020-09-28"
4 "2020-09-27"
5 "2020-09-26"
5 "2020-09-25"
5 "2020-09-24"
5 "2020-09-23"
5 "2020-09-22"
5 "2020-09-21"
5 "2020-09-20"
How about using arithmetics?
select 1 + (row_number() over(order by dt desc) - 1) / 7 rn, dt::date dt
from generate_series(
date_trunc('week', current_date)::date + 5 - interval '5 week -1 day',
date_trunc('week', current_date)::date + 5,
'1 day'
) s(dt)
order by dt desc
generate_series() produces all dates at once. You control the number of weeks that are generated with the value given to week in the literal interval. Then, in the outer query, we use row_number() to enumerate the week numbers.
Demo on DB Fiddle
One sequence for weeks and another one for days. It is flexible, 5 is a parameter. date_trunc('week',now()+'P1W'::interval)::date-2 is this week's saturday.
select
w rno,
date (date_trunc('week',now()+'P1W'::interval)::date-2 + make_interval(weeks => 1-w, days => 1-d)) "Date"
from generate_series(1, 5, 1) w
cross join generate_series(1, 7, 1) d;
output will be as image
SQL Oracle query Sample
select * from (
select * from (
with fifteen as (select trunc(sysdate) + (level * 15)/(24*60) c_time from dual connect by level <= (24*60) / 15 )
select to_number(to_char(c_time, 'hh')) HR,to_char(c_time, 'hh24:mi')||' - '||to_char(c_time+ 15 / (24 * 60), 'hh24:mi') TimeSlots
from fifteen
where extract(hour from cast (c_time as timestamp)) between 2 and 5
) t
)
Oracle Query 1:
with fifteen as (
select CAST( TRUNC( sysdate ) AS TIMESTAMP ) + level * INTERVAL '15' MINUTE c_time,
MOD( LEVEL,4 ) AS quarter
from dual
connect by level <= (24*60) / 15
)
SELECT "2", "3", "4", "5"
FROM (
select EXTRACT( HOUR FROM c_time ) HR,
quarter,
to_char(c_time, 'hh24:mi')||' - '||to_char(c_time + INTERVAL '15' MINUTE, 'hh24:mi') TimeSlots
from fifteen
) t
PIVOT( MAX( timeslots ) FOR HR IN ( 2, 3, 4, 5 ) )
ORDER BY quarter
Oracle Query 2:
SELECT TO_CHAR(two, 'HH24:MI') || ' - ' || TO_CHAR(two +INTERVAL '15' MINUTE,'HH24:MI') AS "2",
TO_CHAR(three,'HH24:MI') || ' - ' || TO_CHAR(three+INTERVAL '15' MINUTE,'HH24:MI') AS "3",
TO_CHAR(four ,'HH24:MI') || ' - ' || TO_CHAR(four +INTERVAL '15' MINUTE,'HH24:MI') AS "4",
TO_CHAR(five ,'HH24:MI') || ' - ' || TO_CHAR(five +INTERVAL '15' MINUTE,'HH24:MI') AS "5"
FROM (
SELECT DATE '1970-01-01' + INTERVAL '2' HOUR + INTERVAL '15' MINUTE * (LEVEL - 1) AS two,
DATE '1970-01-01' + INTERVAL '3' HOUR + INTERVAL '15' MINUTE * (LEVEL - 1) AS three,
DATE '1970-01-01' + INTERVAL '4' HOUR + INTERVAL '15' MINUTE * (LEVEL - 1) AS four,
DATE '1970-01-01' + INTERVAL '5' HOUR + INTERVAL '15' MINUTE * (LEVEL - 1) AS five
FROM DUAL
CONNECT BY LEVEL <= 4
)
Output:
2 3 4 5
------------- ------------- ------------- -------------
02:00 - 02:15 03:00 - 03:15 04:00 - 04:15 05:00 - 05:15
02:15 - 02:30 03:15 - 03:30 04:15 - 04:30 05:15 - 05:30
02:30 - 02:45 03:30 - 03:45 04:30 - 04:45 05:30 - 05:45
02:45 - 03:00 03:45 - 04:00 04:45 - 05:00 05:45 - 06:00
What SQL expression would be able to calculate the number of seconds in any particular year?
For non leap years:
SELECT 365 * 24 * 60 * 60 AS secInYear
FROM dual
And in general:
SqlFiddleDemo
SELECT
24 * 60 * 60 * (
CASE
WHEN MOD(EXTRACT(YEAR FROM sysdate), 400) = 0
OR ( MOD(EXTRACT(YEAR FROM sysdate), 4) = 0 AND MOD(EXTRACT(YEAR FROM sysdate), 100) != 0) THEN 366
ELSE 365
END ) AS secInYear
FROM dual
SELECT
(ADD_MONTHS(TRUNC(SYSDATE, 'YYYY'), 12) - TRUNC(SYSDATE, 'YYYY')) * 86400 SECONDS
FROM
DUAL;
SELECT DAYOFYEAR('2015-12-31') * 24 * 60 * 60 FROM DUAL
DAYOFYEAR will return 365 for New Years Eve for regular years, and 366 for leap years.
Here is how the date is formatted:
XXXXXX001221
This date is for Dec 21
If I want to get yesterdays entries using the CURDATE() function how would I do this?
If you're just doing month-day (indices are based on the string format of CURDATE(), which is YYYY-MM-DD):
SELECT * FROM table_name
WHERE date_field LIKE
CONCAT('%', SUBSTR(DATE_SUB(CURDATE(), INTERVAL 1 DAY) FROM 6 FOR 2),
SUBSTR(DATE_SUB(CURDATE(), INTERVAL 1 DAY) FROM 9 FOR 2));
Or an alternative way using EXTRACT():
SELECT * FROM table_name
WHERE date_field LIKE
CONCAT('%', EXTRACT(MONTH FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
EXTRACT(DAY FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)));
For year as well:
SELECT * FROM table_name
WHERE date_field LIKE
CONCAT('%', SUBSTR(DATE_SUB(CURDATE(), INTERVAL 1 DAY) FROM 3 FOR 2),
SUBSTR(DATE_SUB(CURDATE(), INTERVAL 1 DAY) FROM 6 FOR 2),
SUBSTR(DATE_SUB(CURDATE(), INTERVAL 1 DAY) FROM 9 FOR 2));
SELECT * FROM table_name
WHERE date_field LIKE
CONCAT('%', EXTRACT(YEAR FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
EXTRACT(MONTH FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
EXTRACT(DAY FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)));
EDIT: Instead of WHERE date_field LIKE ... you can use WHERE RIGHT(date_field, 6) = ... as mentioned in codethis' answer:
SELECT * FROM table_name
WHERE RIGHT(date_field, 4) =
CONCAT(EXTRACT(MONTH FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
EXTRACT(DAY FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)));
SELECT * FROM table_name
WHERE RIGHT(date_field, 6) =
CONCAT(EXTRACT(YEAR FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
EXTRACT(MONTH FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)),
EXTRACT(DAY FROM DATE_SUB(CURDATE(), INTERVAL 1 DAY)));
NOTE: You can also use a variable to save calculating DATE_SUB(CURDATE(), INTERVAL 1 DAY) all the time.
SET #yesterday = DATE_SUB(CURDATE(), INTERVAL 1 DAY);
SELECT ...
Try something like:
SELECT * FROM table WHERE RIGHT(date_col, 6) = (SELECT CONVERT(VARCHAR(6), GETDATE()-1, 12) AS [YYMMDD])