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.
Related
I was wondering if you can help me write a query that should just SELECT count(*) but only include data from last hour and group it by minute.
So I have a table that has a createdts so I have the date there. I just want to see how many entries I have in the last hour, but group COUNT(*) per minute.
SELECT COUNT(*) FROM mytable
WHERE createdts >= now()::date - interval '1 hour'
GROUP BY 'every minute'
DATE_TRUNC() does this:
SELECT DATE_TRUNC('minute', createdts), COUNT(*)
FROM mytable
WHERE createdts >= now()::date - interval '1 hour'
GROUP BY DATE_TRUNC('minute', createdts)
ORDER BY DATE_TRUNC('minute', createdts);
I am new to SQL but am having a (probably obvious) issue. My goal is to show all data in the month before the last dated entry. When executing the code block below to find the date a month ago,
SELECT MAX(created_at) - INTERVAL '1 MONTH' AS date
FROM shopify_view
it returns, '2019-11-27 11:40:06'. Makes sense!
But when I try to get all the date with a date above that value:
SELECT created_at AS date
FROM shopify_view
GROUP BY created_at
HAVING created_at >= MAX(created_at) - INTERVAL '1 MONTH'
ORDER BY created_at
it returns the first date as '2018-04-23 10:57:28'. Does not make sense!
what am I missing? Thank you!!
You should use a subquery
SELECT *
FROM shopify_view
Where created_at >= (SELECT MAX(created_at) - INTERVAL '1 MONTH' AS date
FROM shopify_view)
ORDER BY created_at
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 :)
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
In postgresql, how can I generate a series of monthly dates by the format 'YYYY-MM', with the oldest being the creation month of the user up to the current month?
something like :
select to_char(dt, 'YYYY-MM')
from generate_series(
date_trunc('month', (select created_at::date from users where id=1234)),
now(),
'1 month'::interval) dt;
You can even do it in a single query level:
SELECT to_char(generate_series(created_at::date
,now(), interval '1 mon'), 'YYYY-MM') AS month
FROM users
WHERE users_id = 123 -- users_id is unique