how can i fetch record month wise in between two dates in postgresql (grouping dates by their months)? - postgresql

I am using below query for fetching the record month wise but it give
wrong data
SELECT
(count( server_time::timestamp::date)) ,
min(server_time::timestamp::date) as "Month Date"
FROM
complaint_details_v2
WHERE
server_time between '2018/08/01' and '2018/10/30'
GROUP BY
floor((server_time::timestamp::date - '2018/08/01'::date)/30)
ORDER BY
2 ASC
Result
Count Month Date
2774 2018-08-01
5893 2018-08-31
1193 2018-09-30
But result will be
Count Month Date
2774 2018-08-01
5893 2018-09-01
1193 2018-10-01

Use date_trunc
demo:db<>fiddle
SELECT
count(*),
date_trunc('month', servertime)::date as month_date
FROM log
GROUP BY date_trunc('month', servertime)
ORDER BY 2

Related

Previous quarter max month value in big Query

I want to see the previous quarter's max month(as a new column) value in the current quarter using a big query.
When in Q1 2022 it should display Q4 December 2021 as a new column
When in Q2 2022 it should display Q1 March 2022 (in this case 60000)
When in Q3 2022 it should display Q2 June 2022 (in this case 40000)
My data is like below
date Sales
2022-09-01 10000
2022-08-02 20000
2022-07-01 30000
2022-06-01 40000
2022-05-01 30000
2022-04-01 50000
2022-03-01 60000
2022-02-01 10000
2022-01-01 89090
Output
your given result table fits not the task: previous quarter's max month.
Here several outputs. Do you want the maximum of the last months, or the values from three month ago? Both columns are included here.
The formula of the 1st month of quarter can be edit to the last month by changing the 1 to -1. As You want zero values for all other months, you need to multiply this with the other column.
Window function do the job. But for each month there must be one row. This is filled up with the all_months table.
with tbl as
(
Select date("2022-09-01") as dates, 10000 money
union all select date("2022-08-02"), 20000
union all select date("2022-07-01"), 30000
union all select date("2022-06-01"), 40000
union all select date("2022-05-01"), 30000
union all select date("2022-04-01"), 50000
union all select date("2022-03-01"), 60000
union all select date("2022-02-01"), 10000
union all select date("2022-01-01"), 89090
),
all_months as
(select dates,0 from (Select max(dates) A, min(dates) B from tbl), unnest(generate_date_array(A,B,interval 1 month)) dates)
select *,
if( date_trunc(dates,quarter)= date_trunc(date_sub(dates,interval 1 month),quarter),0,1) as first_month_of_quarter,
lag(money_max_this_quarter) over (order by dates) as money_max_last_quarter,
lag(money,3) over (order by dates) as money_three_months_ago,
from
(
select * ,
max(money) over (partition by date_trunc(dates,quarter ) ) as money_max_this_quarter
from
(
Select dates,sum(money) as money from tbl group by 1
union all select * from all_months
)
)
order by 1 desc

Count distinct dates between two timestamps

I want to count %days when a user was active. A query like this
select
a.id,
a.created_at,
CURRENT_DATE - a.created_at::date as days_since_registration,
NOW() as current_d
from public.accounts a where a.id = 3257
returns
id created_at days_since_registration current_d tot_active
3257 2022-04-01 22:59:00.000 1 2022-04-02 12:00:0.000 +0400 2
The person registered less than 24 hours ago (less than a day ago), but there are two distinct dates between the registration and now. Hence, if a user was active one hour before midnight and one hour after midnight, he is two days active in less than a day (active 200% of days)
What is the right way to count distinct dates and get 2 for a user, who registered at 23:00:00 two hours ago?
WITH cte as (
SELECT 42 as userID,'2022-04-01 23:00:00' as d
union
SELECT 42,'2022-04-02 01:00:00' as d
)
SELECT
userID,
count(d),
max(d)::date-min(d)::date+1 as NrOfDays,
count(d)/(max(d)::date-min(d)::date+1) *100 as PercentageOnline
FROM cte
GROUP BY userID;
output:
userid
count
nrofdays
percentageonline
42
2
2
100

How to query hourly aggregated data by date with postgresql?

There is one table:
ID DATE
1 2017-09-16 20:12:48
2 2017-09-16 20:38:54
3 2017-09-16 23:58:01
4 2017-09-17 00:24:48
5 2017-09-17 00:26:42
..
The result I need is the last 7-days of data with hourly aggregated count of rows:
COUNT DATE
2 2017-09-16 21:00:00
0 2017-09-16 22:00:00
0 2017-09-16 23:00:00
1 2017-09-17 00:00:00
2 2017-09-17 01:00:00
..
I tried different stuff with EXTRACT, DISTINCT and also used the generate_series function (most stuff from similar stackoverflow questions)
This try was the best one currently:
SELECT
date_trunc('hour', demotime) as date,
COUNT(demotime) as count
FROM demo
GROUP BY date
How to generate hourly series for 7 days and fill-in the count of rows?
SQL DEMO
SELECT dd, count("demotime")
FROM generate_series
( current_date - interval '7 days'
, current_date
, '1 hour'::interval) dd
LEFT JOIN Table1
ON dd = date_trunc('hour', demotime)
GROUP BY dd;
To work from now and now - 7 days:
SELECT dd, count("demotime")
FROM generate_series
( date_trunc('hour', NOW()) - interval '7 days'
, date_trunc('hour', NOW())
, '1 hour'::interval) dd
LEFT JOIN Table1
ON dd = date_trunc('hour', demotime)
GROUP BY dd;

Getting attendance of an employee with a date series in a particular range in Postgres

I have a attendance table with employee_id, date and punch-in time.
Emp_Id PunchTime
101 10/10/2016 07:15
101 10/10/2016 12:20
101 10/10/2016 12:50
101 10/10/2016 16:31
102 10/10/2016 07:15
Here I have the date only for the working days. I want to get the attendance list of a employee with series of given date period. I need the day also. Result should look like as follows
date | day |employee_id | Intime | outtime |
2016-10-09 | sunday | 101 | | |
2016-10-10 | monday | 101 | 2016-10-10 7:15AM |2016-10-10 4:31 PM |
You can generate a list of dates and then do an outer join on them:
The following displays all days in October:
select d.date, a.emp_id,
min(punchtime) as intime,
max(punchtime) as outtime
from generate_series(date '2016-10-01', date '2016-11-01' - 1, interval '1' day) as d (date)
left join attendance a on d.date = a.punchtime::date
group by d.date, a.emp_id;
order by d.date, a.emp_id;
As you want the first and last timestamp from each day this can be done using a simple group by query.
This will however not repeat the emp_id for the non_existing days.
Something like the following will generate a list of the range of dates (starting and ending with whatever range is found in your punchtime table), with employees and intime, outtime for each. Check the SQL fiddle here:
http://sqlfiddle.com/#!15/d93bd/1
WITH RECURSIVE minmax AS
(
SELECT MIN(CAST(time AS DATE)) AS min, MAX(CAST(time as DATE)) AS max
FROM emp_time
),
dates AS
(
SELECT m.min as datepart
FROM minmax m
RIGHT JOIN emp_time e ON m.min = CAST(e.time as DATE)
UNION ALL
SELECT d.datepart + 1 FROM dates d, minmax mm
WHERE d.datepart + 1 <= mm.max
)
SELECT d.datepart as date, e.emp, MIN(e.time) as intime, MAX(e.time) as outtime FROM dates d
LEFT JOIN emp_time e ON d.datepart = CAST(e.time as DATE)
GROUP BY d.datepart, e.emp
ORDER BY d.datepart;

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

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