How to get min value of all cities of yesterday? - sql

How to get min value(temp) of all cities of yesterday.
I want:
Indore:min value:yesterday date
Bhopal:min value:yesterday date
Mumbai:min value:yesterday date

In Postgres, you can do:
select name, min(temp)
from t
where write_date < current_date and
write_date >= current_date - interval '1 day'
group by name;
You can also write the where clause as:
where date_trunc('day', write_date) = current_date - interval '1 day'
However, using the function date_trunc() prevents the use of the index for the where clause.

select name, min(temp) from table
where date(write_date) BETWEEN TRUNC(SYSDATE - 1)
AND TRUNC(SYSDATE) - 1/86400
group by name
this will do your job

Related

Postgres - how to displays data for the previous year?

I have sql
select
name,
tanggal,
status
from
tbl_person
where
status = 'PROSES'
and date_part('year', tanggal) = 2021 - INTERVAL '1 YEAR'
tanggal is date 2021-01-01
I want to display previous year's data for example in 2020, how to write the correct query?
Using your method:
where status = 'PROSES' and
date_trunc('year', tanggal) = date_trunc('year', current_date) - interval '1 year'
However, I prefer to avoid functions on the column -- so the query is easier to optimize. So I would recommend:
where status = 'PROSES' and
tanggal < date_trunc('year', now()) and
tanggal >= date_trunc('year', now()) - interval '1 year'
This just uses now() rather than current_date because it is easier to type.

Select all rows with date column equal to today's date in postgres to the minute

I essentially want to run a query like:
SELECT * FROM t where date={time right now to the minute}
Use date_trunc() for your exact question:
where date = date_trunc('minute', now())
However, I suspect you really want the span of one minute:
where date >= date_trunc('minute', now()) and
date < date_trunc('minute', now()) + interval '1 minute'

SQL: Select average value of column for last hour and last day

I have a table like below image. What I need is to get average value of Volume column, grouped by User both for 1 hour and 24 hours ago. How can I use avg with two different date range in single query?
You can do it like:
SELECT user, AVG(Volume)
FROM mytable
WHERE created >= NOW() - interval '1 hour'
AND created <= NOW()
GROUP BY user
Few things to remember, you are executing the query on same server with same time zone. You need to group by the user to group all the values in volume column and then apply the aggregation function like avg to find average. Similarly if you need both together then you could do the following:
SELECT u1.user, u1.average, u2.average
FROM
(SELECT user, AVG(Volume) as average
FROM mytable
WHERE created >= NOW() - interval '1 hour'
AND created <= NOW()
GROUP BY user) AS u1
INNER JOIN
(SELECT user, AVG(Volume) as average
FROM mytable
WHERE created >= NOW() - interval '1 day'
AND created <= NOW()
GROUP BY user) AS u2
ON u1.user = u2.user
Use conditional aggregation. Postgres offers very convenient syntax using the FILTER clause:
SELECT user,
AVG(Volume) FILTER (WHERE created >= NOW() - interval '1 hour' AND created <= NOW()) as avg_1hour,
AVG(Volume) FILTER (WHERE created >= NOW() - interval '1 day' AND created <= NOW()) as avg_1day
FROM mytable
WHERE created >= NOW() - interval '1 DAY' AND
created <= NOW()
GROUP BY user;
This will filter out users who have had no activity in the past day. If you want all users -- even those with no recent activity -- remove the WHERE clause.
The more traditional method uses CASE:
SELECT user,
AVG(CASE WHEN created >= NOW() - interval '1 hour' AND created <= NOW() THEN Volume END) as avg_1hour,
AVG(CASE WHEN created >= NOW() - interval '1 day' AND created <= NOW() THEN Volume END) as avg_1day
. . .
SELECT User, AVG(Volume) , ( IIF(created < DATE_SUB(NOW(), INTERVAL 1 HOUR) , 1 , 0) )IntervalType
WHERE created < DATE_SUB(NOW(), INTERVAL 1 HOUR)
AND created < DATE_SUB(NOW(), INTERVAL 24 HOUR)
GROUP BY User, (IIF(created < DATE_SUB(NOW(), INTERVAL 1 HOUR))
Please Tell me about it's result :)

PostgreSQL query interval data

I'm trying to perform a query which I can't figure out how to write. I have a claims table
claims table:
- id
- date_received
I want to grab the new claim count for each day for over 30 days. The naive solution I was trying to come up with was this.
select count(*)
from claims
where date_received
BETWEEN CURRENT_DATE - interval '1 month'
AND CURRENT_DATE
group by date_received;
This works but it groups by exact timestamp and not same day. How could I make it so it groups by same day?
EDIT
I was able to figure it our updated query:
select date_received::date as date, count(id) as new_claims
from claims
where date_received BETWEEN CURRENT_DATE - interval '1 month'
AND CURRENT_DATE
group by date_received::date
order by date;
Presumably, claims arrive in the past, not the future, so you would want:
select date_received::date, count(*)
from claims
where date_received >= CURRENT_DATE - interval '1 month' and
date_received < CURRENT_DATE
group by date_received::date
order by date_received::date;
Building on Gordon's answer, you can use date_trunc(precision, timestamp) to get what you want:
select date_received::date, count(*)
from claims
where date_received >=
date_trunc('day', CURRENT_DATE - interval '1 month')
and date_received < CURRENT_DATE
group by date_received::date
order by date_received::date;
See date_trunc() for details.

Postgresql get max row group by column

I am trying to get the max row from the sum of daily counts in a table. I have looked at several posts that look similar, however it doesn't seem to work. I have tried to follow
Get MAX row for GROUP in MySQL
but it doesn't work in Postgres. Here's what I have
select source, SUM(steps) as daily_steps, to_char("endTime"::date, 'MM/DD/YYYY') as step_date
from activities
where user_id = 1
and "endTime" <= CURRENT_TIMESTAMP + INTERVAL '1 day'
and "endTime" >= CURRENT_TIMESTAMP - INTERVAL '7 days'
group by source, to_char("endTime"::date, 'MM/DD/YYYY')
This returns the following
source, daily_steps, step_date
"walking";750;"11/17/2015"
"walking";821;"11/22/2015"
"walking";106;"11/20/2015"
"running";234;"11/21/2015"
"running";600;"11/24/2015"
I would like the result to return only the rows that have the max value for daily_steps by source. The result should look like
source, daily_steps, step_date
"walking";821;"11/22/2015"
"running";600;"11/24/2015"
Postgres offers the convenient distinct on syntax:
select distinct on (a.source) a.*
from (select source, SUM(steps) as daily_steps, to_char("endTime"::date, 'MM/DD/YYYY') as step_date
from activities a
where user_id = 1 and
"endTime" <= CURRENT_TIMESTAMP + INTERVAL '1 day' and
"endTime" >= CURRENT_TIMESTAMP - INTERVAL '7 days'
group by source, to_char("endTime"::date, 'MM/DD/YYYY')
) a
order by a.source, daily_steps desc;