I have the following SQLite statement:
(strftime('%j', date( s.my_time, '-3 days', 'weekday 3'))) / 7 AS ww
How can I accomplish this same function on s.my_time in postgresql?
In SQLite:
select (strftime('%j',
date( '2022-09-03 21:03:44', '-3 days', 'weekday 3'))) / 7 AS ww;
34
In Postgres:
select extract(doy from '2022-08-31'::timestamp - '3 days'::interval)::integer/7;
?column?
----------
34
Though if you do:
select to_char('2022-09-03 21:03:44'::timestamp - '3 days'::interval, 'WW');
to_char
---------
35
You get a different week as without converting the extract output to integer you get:
select extract(doy from '2022-08-31'::timestamp)/7;
?column?
---------------------
34.7142857142857143
Related
I have an oracle query to change it into postgres
SELECT cast(to_char(ADD_MONTHS(TRUNC(ADD_MONTHS(SYSDATE, -6),'MM'),LEVEL - 1),'MMYYYY') as number) monthid,
to_char (ADD_MONTHS(TRUNC(ADD_MONTHS(SYSDATE, -6),'MM'), LEVEL - 1),'MON-YYYY') monthdesc
From dual
CONNECT BY LEVEL <= MONTHS_ BETWEEN (SYSDATE, ADD_MONTHS (SYSDATE, -6)) + 1;
I tried with CTE and generate_series, but stuck somewhere to get result set
---------------------
MONTHID MONTHDESC
---------------------
172022 JUL-2022
82022 AUG-2022
92022 SEP-2022
102022 OCT-2022
112022 NOV-2022
122022 DEC-2022
12023 JAN-2023
This will generate a list of the last six months:
select to_char(g.dt, 'mmyyyy') as monthid,
to_char(g.dt, 'MON-yyyy') as monthdesc
from generate_series(date_trunc('month', current_date) - interval '6 month',
date_trunc('month', current_date), interval '1 month') as g(dt)
However this will return 072022 for July 2022, not 172022 as in your sample data.
select CAST(current_date as timestamp)
+ to_char(timestamp '2019-07-08 09:00:00','YYYY-MM-DD HH24:MI:SS')::TIMESTAMP;
Current output: 2019-08-02 00:00:002019-07-08 09:00:00
You can use the DATEADD() function or the INTERVAL syntax to add specific units of time to another date/timestamp.
SELECT DATEADD(hour, 9, current_date);
-- date_add
-- ---------------------
-- 2019-08-05 09:00:00
SELECT current_date + INTERVAL '9 hours';
-- ?column?
-- ---------------------
-- 2019-08-05 09:00:00
So I'm having this query:
SELECT
TO_CHAR(date_part('hour', created_at), 'YYYY-MM-DD HH24'),
to_char(created_at, 'day') ",
COUNT(*) AS "
FROM table
GROUP BY 1,2
ORDER BY 1 DESC
When I execute the query I get this:
ERROR: multiple decimal points
Searching stackoverflow I found some recommendations here:
How to format bigint field into a date in Postgresql? but I don't get why do I have to divide by 1000 and how this would apply in the case of the date_part function.
I assume created_at is a timestamp?.. I'm choosing from date_part(text, timestamp) and date_part(text, interval), if so date_part will return a double precision, to which you try to apply the mask 'YYYY-MM-DD HH24', eg:
v=# select date_part('hour', now());
date_part
-----------
9
and I don't see how you could possibly get year, month, day and hour from nine...
Yet I assume you wanted to apply the mask against truncated date to the hour precision, which is done with date_trunc(text, timestamp):
v=# select date_trunc('hour', now());
date_trunc
------------------------
2017-06-20 09:00:00+01
(1 row)
so now you can apply the time format:
v=# select to_char(date_trunc('hour', now()),'YYYY-MM-DD HH24');
to_char
---------------
2017-06-20 09
(1 row)
but if this is what you want, then you don't need to truncate time at all:
v=# select to_char(now(),'YYYY-MM-DD HH24');
to_char
---------------
2017-06-20 09
(1 row)
https://www.postgresql.org/docs/current/static/functions-datetime.html
This question is asked many times and one of the suggested queries to get months between 2 dates is not working.
SELECT date_part('month',age('2016-06-30', '2018-06-30'))
The result of this query is 0. It should be 24 months. Because the months are 06 in both dates.
This works, but it is a bit clumsy compared to the sql server function:
SELECT date_part ('year', f) * 12 + date_part ('month', f)
FROM age ('2016-06-30', '2018-06-30') f
Like sql server (I think):
DATEDIFF(month, date1, date2)
Is there no simple way (like the above) to calculate the months between 2 dates in Postgresql? I prefer not to use a function if it is possible.
Unfortunately you already have the most elegant solution.
If you look at the documentation for extract (same as date_part):
https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
month
For timestamp values, the number of the month within the year (1 - 12) ; for interval values, the number of months, modulo 12 (0 - 11)
SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 2
SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months');
Result: 3
SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months');
Result: 1
For your problem it would be nice if there was a version of month that wasn't modulo 12 but that doesn't exist.
The option you have (extract the year * 12 + month) is the best option there is.
Edit
If you do want to create a function then see the following two functions:
CREATE OR REPLACE FUNCTION get_months(i interval) RETURNS double precision AS $$
SELECT date_part ('year', i) * 12 + date_part ('month', i) ;
$$ LANGUAGE SQL IMMUTABLE;
SELECT get_months(age('2016-06-30', '2018-06-30'));
Or
CREATE OR REPLACE FUNCTION get_months(to_date date, from_date date) RETURNS double precision AS $$
SELECT date_part ('year', f) * 12 + date_part ('month', f)
FROM age (to_date, from_date) f;
$$ LANGUAGE SQL IMMUTABLE;
SELECT get_months('2016-06-30', '2018-06-30');
You can actually create both then just use whichever suits your code.
This will give you the # of months between two dates excluding days.
CREATE OR REPLACE FUNCTION get_months_between(to_date date, from_date date) RETURNS double precision AS $$
SELECT (date_part ('year', to_date) * 12 + date_part ('month', to_date)) - (date_part ('year', from_date) * 12 + date_part ('month', from_date))
$$ LANGUAGE SQL IMMUTABLE;
I execute the justify_days() in postgres sql
SELECT justify_days(interval '100 month')
output
"8 years 4 mons"
But I am using subquery instead of 100
SELECT justify_days(interval '(SELECT 100) month')
it shows an error
How can I fix it?
Try this,
select 100 returns 100 as integer datatype, So you need to cast it as interval and concatenate like below
select justify_days(cast((select 100)||' month' as interval))
Result:
justify_days
interval
--------------
8 years 4 mons
FYI,
select cast((select 100)||' month' as interval)
gives the same output
Result:
justify_days
interval
--------------
8 years 4 mons