Case conditions giving not expected results - postgresql

In my query i have some case condition to look over hours in lastoccurrence column then as shown in specific cases it should print in aging_range column either 6 hrs, 12 hrs, 24 hrs, 48 hrs or else > 1 week. Problem is even if as in picture hours = 1 i receive > 1 week. What is wrong with my query?
Query:
CREATE OR REPLACE VIEW schemaA.test
AS SELECT tableA.lastoccurrence,
date_part('hours'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) AS hours,
date_part('days'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) AS days,
age(timezone('GMT'::text, now()), tableA.lastoccurrence) AS age,
CASE
WHEN date_part('hours'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) >= 1::double precision AND date_part('hours'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) <= 6::double precision AND date_part('days'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) = 0::double precision THEN '6 hrs'::text
WHEN date_part('hours'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) >= 7::double precision AND date_part('hours'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) <= 12::double precision AND date_part('days'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) = 0::double precision THEN '12 hrs'::text
WHEN date_part('hours'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) >= 13::double precision AND date_part('hours'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) <= 24::double precision AND date_part('days'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) = 0::double precision THEN '24 hrs'::text
WHEN date_part('hours'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) >= 25::double precision AND date_part('hours'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) <= 48::double precision AND date_part('days'::text, timezone('GMT'::text, now()) - tableA.lastoccurrence) = 0::double precision THEN '48 hrs'::text
ELSE '> 1 week'::text
END AS aging_range
FROM tmp.tableA;
Result:

The problem is that the timestamps were less than an hour in the past when you ran the query, and your CASE statement doesn't contain a case for “hours = 0”, so the ELSE branch was taken.
The CASE expression is overly complicated. I suggest something like:
SELECT CASE
WHEN age(lastoccurrence AT TIME ZONE 'UTC') > '1 week'
THEN '> 1 week'
WHEN age(lastoccurrence AT TIME ZONE 'UTC') > '2 days'
THEN '1 week'
WHEN age(lastoccurrence AT TIME ZONE 'UTC') > '1 day'
THEN '2 days'
WHEN age(lastoccurrence AT TIME ZONE 'UTC') > '12 hours'
THEN '1 day'
WHEN age(lastoccurrence AT TIME ZONE 'UTC') > '6 hours'
THEN '12 hours'
ELSE '6 hours'
END
FROM tmp.tablea;

Related

Query max and min in a fixed range of time of each day interval POSTGRES

I have a query below to query max and min of day interval in a range of time ( current_date - 2 to current_date - 1). Now, I need to query dayshift and extra shift separately ( dayshift from 5am to 3pm, extra shift will be the remains).
select sum(gap) from (
select to_char(time_stamp, 'yyyy/mm/dd') as day,
EXTRACT(EPOCH FROM (max(time_stamp) - min(time_stamp))) /3600 as gap
from group_table_debarker
where time_stamp >= (current_date - 2)
and time_stamp <= (current_date - 1)
and to_char(time_stamp, 'hh:mi') > '03:00' and to_char(time_stamp, 'hh:mi') < '15:00'
group by to_char(time_stamp, 'yyyy/mm/dd')
) as xxx
select sum(gap) from (
select to_char(time_stamp, 'yyyy/mm/dd') as day,
EXTRACT(EPOCH FROM (max(time_stamp) - min(time_stamp))) /3600 as gap
from group_table_debarker
where time_stamp >= (current_date - 2)
and time_stamp <= (current_date - 1)
and to_char(time_stamp, 'hh:mi') > '03:00' and to_char(time_stamp, 'hh:mi') < '15:00'
group by to_char(time_stamp, 'yyyy/mm/dd')
) as xxx
I've tried this but result wasn't expected

PostgreSQL - Add days to current_data with condition

I'm trying to add a day to current_date in between only when from hour is bigger then to hour
can any one help?
see code:
AND EXISTS(SELECT *
FROM jsonb_array_elements((${hours})::jsonb) hours(e)
WHERE hours.e->'active' = 'true'
AND now() BETWEEN
current_date +
(LEFT(hours.e->>'from', 2))::INTEGER * INTERVAL '1 HOUR' +
(RIGHT(hours.e->>'from', 2))::INTEGER * INTERVAL '1 MINUTE' AND
current_date +
// add day if from is bigger then to
(LEFT(hours.e->>'to', 2))::INTEGER * INTERVAL '1 HOUR' +
(RIGHT(hours.e->>'to', 2))::INTEGER * INTERVAL '1 MINUTE' )
a

How to get the 1st 6months i.e.(1-26weeks) and last 6months (26-52 weeks) from last year & also get last 5weeks from current date using postgresql

How to get the 1st 6months i.e.(1-26weeks) and last 6months (26-52 weeks) from last year & also how to get last 5weeks from current date using postgresql.
Like the below table structure
Id Title Description current_week_number current_year
-----------------------------------------------------
123 abc descr 48 2021
456 def descr1 45 2020
Based on the week number and year I'm trying to fetch the data.
can anyone help on this?
Thanks
Query the table on the last 6 months until now :
SELECT *
FROM your_table
WHERE (current_year || '0101') :: date + interval '7 days' * current_week >= Now() - interval '6 months'
AND (current_year || '0101') :: date + interval '7 days' * current_week <= Now()
Query the table between the last 12 months and the last 6 months from now :
SELECT *
FROM your_table
WHERE (current_year || '0101') :: date + interval '7 days' * current_week <= Now() - interval '6 months'
AND (current_year || '0101') :: date + interval '7 days' * current_week >= Now() - interval '12 months'
Query the table for the first 6 months of the current year :
SELECT *
FROM your_table
WHERE (current_year || '0101') :: date + interval '7 days' * current_week >= (extract(year from Now()) || '0101') :: date
AND (current_year || '0101') :: date + interval '7 days' * current_week <= (extract(year from Now()) || '0101') :: date + interval '6 months'
Query the table for the last 6 months of the current year :
SELECT *
FROM your_table
WHERE (current_year || '0101') :: date + interval '7 days' * current_week >= (extract(year from Now()) || '0101') :: date + interval '6 months'
AND (current_year || '0101') :: date + interval '7 days' * current_week <= (extract(year from Now()) || '0101') :: date + interval '12 months'
--records from 1st half of this year, based on week number
select Id, Title, Description, current_week_number, current_year
from your_table
where current_year=extract('year' from now())::int
and current_week_number<=26;
--records from 2nd half of this year, based on week number
select Id, Title, Description, current_week_number, current_year
from your_table
where current_year=extract('year' from now())::int
and current_week_number>26;
As to the original form of the question, getting the actual weeks:
using generate_series(date,date,interval) and extract('field' from date).
with first_26_weeks_of_last_year as
( select extract('week' from weeks) weeks
from generate_series(
make_date( extract('year' from 'today'::timestamp-'1 year'::interval)::int,
1,
1
),
make_date( extract('year' from 'today'::timestamp-'1 year'::interval)::int,
1,
1
)+'25 weeks'::interval,
'1 week'::interval) weeks),
last_6_months_of_last_year as
( select extract('week' from weeks) weeks
from generate_series(
make_date( extract('year' from 'today'::timestamp-'1 year'::interval)::int,
12,
31
),
make_date( extract('year' from 'today'::timestamp-'1 year'::interval)::int,
12,
31
)-'6 months'::interval,
'1 week'::interval) weeks),
five_weeks_from_this_week as
( select extract('week' from weeks) weeks
from generate_series(
'today'::date,
'today'::date+'4 weeks'::interval,
'1 week'::interval) weeks)
select 'first_26_weeks_of_last_year',a.weeks
from first_26_weeks_of_last_year a
union all
select 'last_6_months_of_last_year',a.weeks
from last_6_months_of_last_year a
union all
select 'five_weeks_from_this_week',a.weeks
from five_weeks_from_this_week a;

PostgreSQL Extract Year from Timestamp and then apply Interval Calculation

I'd like to filter a dataset to include everything with a created_date >= current year plus 5 full years prior. If I ran this today, I'd want anything with a created_date >= 01/01/2016 (2021 - 5 = 2016)
where extract(year from created_date) >= extract(year from current_date) - interval '5 years'
of course this doesn't work with double precision datatype. Any thoughts? Thank you.
Use date_trunc() to "round" the dates to the first of January.
where date_trunc('year', created_date) >= date_trunc('year', current_timestamp) - interval '5 years'
But the "I'd want anything with a created_date >= 01/01/2016" seems to indicate you might want:
where created_date >= date_trunc('year', current_timestamp) - interval '5 years'

Postgresql compare two select result on the same table

I compare results from two selects and get 1 or 0 as a final result.
Below query syntax is good but this query causes timeout.
SELECT (CASE WHEN (
select count(*) from order where ordered_date > (NOW() - INTERVAL '120 minutes')
and order_ordered = current_date) >
(select count(*)/3
from order
where ordered_date > (NOW() - INTERVAL '2 days' - INTERVAL '120 minutes')
and ordered_date < (NOW() - INTERVAL '2 days'))
THEN 1 ELSE 0 end);
Therefore, i try to optimize the query to use an alias for each select as below :
select (case when a > b then 1 else 0 end) from (select count(*) from order where ordered_date > (NOW() - INTERVAL '120 minutes')
and order_ordered = current_date) as a,
from (select count(*)/3
from order
where ordered_date > (NOW() - INTERVAL '2 days' - INTERVAL '120 minutes')
and ordered_date < (NOW() - INTERVAL '2 days'))as b;
I have syntax error near "from", in my memory this kind of syntax works on mysql.
Could you please advise me if there a possiblity to use two times of "from" by using alias on Postgresql or if you know another possility i am a taker.
Sample:
First query gives : select count(*) from order where ordered_date > (NOW() - INTERVAL '120 minutes') and order_ordered = current_date -> 60
Seconde query gives : select count(*)/3 from order where ordered_date > (NOW() - INTERVAL '2 days' - INTERVAL '120 minutes') and ordered_date < (NOW() - INTERVAL '2 days') -> 20
Final condition : case when (60 > 20 then 1 else 0 end)
Result expected : 1
Thanks
I suggest using SELECT in WITH (here documentation).
WITH orders_current_date AS (
SELECT count(*)
FROM order
WHERE ordered_date > (NOW() - INTERVAL '120 minutes')
AND order_ordered = current_date)
), orders_interval AS (
SELECT count(*)/3
FROM order
WHERE ordered_date > (NOW() - INTERVAL '2 days' - INTERVAL '120 minutes')
AND ordered_date < (NOW() - INTERVAL '2 days')
)
SELECT
CASE
WHEN SELECT * FROM orders_current_date > SELECT * FROM orders_interval
THEN '1'
ELSE
0
END;