In SQL(postgresql) How to group based on a "timestamp without time zone" column? - postgresql

I am trying to write some queries to group things based on each month in postgresql.
Say we have a table "crimes" which has 2 columns "activity date"(timestamp without time zone) and "zipcode"(character varying(5)), how to query the number of crimes for each month given a zipcode?
eg:
table "crimes":
activity date zipcode
2014-11-22 00:52:00 12345
2014-10-22 00:52:00 12345
2014-10-24 00:52:00 12345
2014-12-22 00:52:00 54321
input: given zipcode"12345"
output: return
month count
2014-10 2
2014-11 1

Try:
select
extract(year from activity_date) as year,
to_char(activity_date, 'Mon') as month,
count(*) as count
from
crimes
group by
1,extract(month from activity_date);

How to get the month from a timestamp (with/out timezone) in PostgreSQL?
Use the function EXTRACT(field FROM source)
SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 2
Link to documentation: https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT

Related

How to sum for previous n number of days for a number of dates in PostgreSQL

I have a list of dates each with a value in Postgresql.
For each date I want to sum the value for this date and the previous 4 days.
I also want to sum the values for the start of that month to the present date. So for example:
For 07/02/2021 sum all values from 07/02/2021 to 01/02/2021
For 06/02/2021 sum all values from 06/02/2021 to 01/02/2021
For 31/01/2021 sum all values from 31/01/2021 to 01/01/2021
The output should look like, will be created as two separate tables:
Output
Any help would be appreciated.
Thanks
Sample data and structure: dbfiddle
For first part of query:
select date,
value,
sum(value) over (
order by to_date(date, 'DD/MM/YYYY')
rows between 4 preceding and current row) as five_day_period
from your_table_name
order by to_date(date, 'DD/MM/YYYY') desc;
For second part of query:
select date,
value,
sum(value)
over (
partition by regexp_replace(date, '[0-9]{2}/(.+)', '\1')
order by to_date(date, 'DD/MM/YYYY')
rows between unbounded preceding and current row) as month_to_date
from your_table_name
order by to_date(date, 'DD/MM/YYYY') desc;

Make date_trunc() start on Sunday instead of Monday

Select date_trunc('week',dateTime) Date_week, Max(Ranking) Runing_Total_ID
from (select datetime, id , dense_rank () over (order by datetime) as Ranking
from Table1)
group by 1
This query is working for me to give me the running total of total IDs by week. But the week starts on Monday in Postgres by default. Is there any way to change the week start to SUNDAY?
Shift the timestamp back and forth:
Add a day before feeding the timestamp to date_trunc(), then subtract again:
SELECT date_trunc('week', datetime + interval '1 day') - interval '1 day' AS date_week
, max(ranking) AS runing_total_id
FROM (
SELECT datetime, dense_rank() OVER (ORDER BY datetime) AS ranking
FROM table1
) sub
GROUP BY 1;
See:
PostgreSQL custom week number - first week containing Feb 1st

Retrieve Records for month,datewise group by day in postgres

I have table time_slot where i have columns like date,start_time,end_time,user.
I want to retrieve records like say if I give the month and year along with user, what is the slots available for a particular user day wise for a month. Say user can have 3slots on a day & 0 on a day.
I am using Postgres and my date column is a date, time column is time. I am trying to do this in a Java web application and the date will be picked using a jquery datepicker. From where I'm sending as month, year and user.
Sample Data of table.
Date start-time end-time user
2019-09-01 12:21:34 13:21:34 user1
2019-09-01 14:21:34 15:21:34 user1
2019-09-01 17:21:34 17:21:34 user1
2019-09-03 12:21:34 13:21:34 user1
2019-09-03 12:21:34 13:21:34 user1
I would like to create a query that gives the time-slots of user concating start-time & end-time column and groups the results by date for a month as follows:
Date count_of_slots
2019-09-01 3
2019-09-02 0
2019-09-03 2
I have tried the below Query.
select distinct kt.start_time,kt.end_time,DATE(kt.slot_date),count(kt.slot_date)
from time_slot as kt
WHERE date_trunc('month',to_timestamp(kt.start_time, 'yy-mm-dd HH24:MI:SS.MS') + interval '1 day')
= date_trunc('month',to_timestamp(:startdate, 'yy-mm-dd HH24:MI:SS.MS') + interval '1 day' )
group by DATE(kt.slot_date) order by cb.start_time.
After getting result as expected above format, I need to loop through date to get the time-slots for that day and store in json as below.
{
"Date" : "2019-09-01",
"count" : "3",
"time-slot" : [
"12:21:34 - 13:21:34","14:21:34 - 15:21:34","17:21:34 - 17:21:34"]
}
Any suggestion and leads are welcomed.
Disclaimer: You should really upgrade your Postgres version!
demo:db<>fiddle
You need to join a date series against your data set. This can be done using the generate_series() function.
SELECT
gs::date,
COUNT(the_date)
FROM
time_slot ts
RIGHT JOIN
generate_series('2019-09-01', '2019-09-05', interval '1 day') gs ON ts.the_date = gs
GROUP BY gs
If you want to get the time_slots as well, simply add:
ARRAY_AGG(start_time || ' - ' || end_time) AS time_slot

Postgres count by date with timezone

I want to query a table to find out a count of objects created by date, day and month in Postgres.
Fetch count for last 30 days
SELECT d.date, count(se.id)
FROM (SELECT to_char(date_trunc('day', (current_date - offs)), 'YYYY-MM-DD') AS date
FROM generate_series(0, 30) AS offs) d LEFT OUTER JOIN
someTable se
ON d.date = to_char(date_trunc('day', se.created_at), 'YYYY-MM-DD')
GROUP BY d.date;
Fetch count by day
select to_char(created_at,'day') as Day,
extract(month from created_at) as Date,
count("id") as "Count"
from someTable
group by 1,2
Fetch count by month
select to_char(created_at,'Mon') as mon,
extract(year from created_at) as yyyy,
count("id") as "Count"
from someTable
group by 1,2
This works fine for me. The problem that I have is, I want the data to be fetched based on different timezones. I have stored the time in UTC. I would be able to run these queries with different timezones.
What is the best way to do it?
Check this answer to get the datetime in Postgres with different timezone.
Fetch count for last 30 days
SELECT d.date, count(se.id)
FROM (SELECT to_char(date_trunc('day', (current_date - offs)), 'YYYY-MM-DD') AS date
FROM generate_series(0, 30) AS offs) d LEFT OUTER JOIN
someTable se
ON d.date = to_char(date_trunc('day', se.created_at::timestamp with time zone at time zone 'EST'), 'YYYY-MM-DD')
GROUP BY d.date;
Fetch count by day
select to_char(created_at::timestamp with time zone at time zone 'EST','day') as Day,
extract(month from created_at) as Date,
count("id") as "Count"
from someTable
group by 1,2
Fetch count by month
select to_char(created_at::timestamp with time zone at time zone 'EST','Mon') as mon,
extract(year from created_at) as yyyy,
count("id") as "Count"
from someTable
group by 1,2
Also refer to this Postgres documentation to learn about timezone with datetime.

Customize query of postgresql

I am using postgresql database, for i am trying to achieve like i have two queries and but i don't want to use multiple queries so is it possible to manage by single query ?
Query 1 :
select coalesce(sum("dummy"),0) as sum from generate_series ('2014-09-09 00:00:00'::timestamp,'2014-09-09 23:59:59','1 minute')
minutes(minute) LEFT JOIN report ON
minutes.minute=date_trunc('minute', report.fetchdate)
AND fetchdate >= '2014-09-09 00:00:00' AND fetchdate <= '2014-09-09 23:59:00'
AND entity_id ='0' group by minute order by minute
OUTPUT:
Total count of dummy field for each minutes of each day it means each day have total (24*60=1440) records
Note : This Query Using for single Day
Query2 :
select date(day)as day,coalesce(sum("dummy"),0) as sum from generate_series ('2014-09-06 00:00:01'::date,'2014-09-12 23:59:59'::date,'1 day'::interval) days(day) LEFT JOIN report ON days.day=date_trunc('day', report.fetchdate) AND entity_id ='0' group by day order by day
OUTPUT:
give total count of dummy field for each day between day 2014-09-06 to 2014-09-12 it means total 7 records (Date : 6,7,8,9,10,11,12)
Note :This Query using for more than 1 days
Required Output:
1) Need to see total count of dummy field of each day between specified date(Output of 2nd query)
2) Need to see maximum call of each day
Ex :
Suppose i am search by any two days then need to break in single date and get data for each minute of each date and whenever we have maximum count of dummy field of particular day then need to show as output maximum call for each day
select
date_trunc('day', minute) as day,
sum(minute_sum) as day_sum,
max(minute_sum) as max_minute_sum
from (
select
minute,
coalesce(sum("dummy"),0) as minute_sum
from
generate_series(
'2014-09-06'::timestamp,
'2014-09-13'::timestamp - interval '1 minute',
'1 minute'
) minutes(minute)
left join
report on
minutes.minute = date_trunc('minute', report.fetchdate)
and entity_id ='0'
group by minute
) s
group by 1
order by 1