I have the query below which returns 12 months rolling data. So if I run it today it brings data back from 23rd August 2015 to 23rd August 2016. Now ideally I would like it to start from the 1st August 2015 and if I was to run it again next month it would start from 1stSeptember 2015. Is this possible to do? Thanks
select
Date
Street
Town
Incidents
IncidentType A
IncidentType B
IncidentType C
FROM
(
select
COUNT(I.INC_NUM) as Incidents,
COUNT(case when i.INC_TYPE = ''A'' THEN 1
end)
"IncidentType A"
COUNT(case when i.INC_TYPE = ''B'' THEN 1
end)
"IncidentType B"
COUNT(case when i.INC_TYPE = ''C'' THEN 1
end)
"IncidentType C"
FROM Table i
GROUP BY i.INC_NUM
) i
where Date >= (now()-('12 months'::interval))
Your code suggests that you are using Postgres. If the code works and you just need to adjust the where clause, use date_trunc():
where Date >= date_trunc('month', now() - ('12 months'::interval))
Related
I have this postgresql query
SELECT pick.min_date, extract('week' from pick.min_date) as week FROM account_invoice inv
left join stock_picking pick on inv.origin=pick.name
WHERE inv.number ='INV/2022/17359'
and the results are
min_date | week
2022-08-11 02:01:00 | 32
What I need for the week column is number 2 because the date (11) is in the 2nd weeks of august. Any help will be great. Thank you
Subtract the week number of the target date from the week number of the first day of the month of the target date and add one. Here is your query with this modification.
SELECT pick.min_date,
extract('week' from pick.min_date) -
extract('week' from date_trunc('month', pick.min_date)) + 1 as week
FROM account_invoice inv
left join stock_picking pick on inv.origin=pick.name
WHERE inv.number ='INV/2022/17359';
Demo
SELECT
extract('week' from '2022-08-11'::date) -
extract('week' from date_trunc('month', '2022-08-11'::date)) + 1;
-- yields 2
I use date part for these extractions
select
((date_part('day', dt::date)::integer - 1) / 7) +1 as currentweekofthemonth,
date_part('week', dt::date) AS weekoftheyear,
date_part('month', dt::date) AS mon,
date_part('year', dt::date) AS yr from
(select '2022-08-11 02:01:00' as dt) as drt ;
OUTPUT :
currentweekofthemonth weekoftheyear mon yr
2 32 8 2022
I am currently writing a Crystal Report that has a DB2 query as its backend. I have finished the query but am stuck on the date portion of it. I am going to be running it twice a month - once on the 16th, and once on the 1st of the next month. Here's how it should work:
If I run it on the 16th of the month, it will give me results from the 1st of that same month to the 15th of that month.
If I run it on the 1st of the next month, it will give me results from the 16th of the previous month to the last day of the previous month.
This comes down a basic bi-monthly report. I've found plenty of hints to do this in T-SQL, but no efficient ways on how to accomplish this in DB2. I'm having a hard time wrapping my head around the logic to get this to consistently work, taking into account differences in month lengths and such.
There are 2 expressions for start and end date of an interval depending on the report date passed, which you may use in your where clause.
The logic is as follows:
1) If the report date is the 1-st day of a month, then:
DATE_START is 16-th of the previous month
DATE_END is the last day of the previous month
2) Otherwise:
DATE_START is 1-st of the current month
DATE_END is 15-th of the current month
SELECT
REPORT_DATE
, CASE DAY(REPORT_DATE) WHEN 1 THEN REPORT_DATE - 1 MONTH + 15 ELSE REPORT_DATE - DAY(REPORT_DATE) + 1 END AS DATE_START
, CASE DAY(REPORT_DATE) WHEN 1 THEN REPORT_DATE - 1 ELSE REPORT_DATE - DAY(REPORT_DATE) + 15 END AS DATE_END
FROM
(
VALUES
DATE('2020-02-01')
, DATE('2020-02-05')
, DATE('2020-02-16')
) T (REPORT_DATE);
The result is:
|REPORT_DATE|DATE_START|DATE_END |
|-----------|----------|----------|
|2020-02-01 |2020-01-16|2020-01-31|
|2020-02-05 |2020-02-01|2020-02-15|
|2020-02-16 |2020-02-01|2020-02-15|
In Db2 (for Unix, Linux and Windows) it could be a WHERE Condition like
WHERE
(CASE WHEN date_part('days', CURRENT date) > 15 THEN yourdatecolum >= this_month(CURRENT date) AND yourdatecolum < this_month(CURRENT date) + 15 days
ELSE yourdatecolum > this_month(CURRENT date) - 1 month + 15 DAYS AND yourdatecolum < this_month(CURRENT date)
END)
Check out the THIS_MONTH function - there are multiple ways to do it. Also DAYS_TO_END_OF_MONTH might be helpful
I've been trying to calculate 7 Day Return Rate (also known as Classic Retention Rate, as described here: https://www.braze.com/blog/calculate-retention-rate/) and then taking a 30 day average to reduce noise in Postgresql.
However, I'm sure I'm doing something wrong. First of all, the numbers look waaay higher than intuitively I feel they should be (generally around 5% for the rest of the sector). Also, I believe the first 7 days should show 0, as theoretically users should take at least 7 days to count as a "return". However, I get around 40-70%, as shown below.
Would someone mind taking a look at the code below and seeing if there are any errors? 7 Day Return Rate is a really common metric for apps, and I haven't found any questions using postgresql that calculate it to this level of sophistication on Stack Exchange (or even the rest of the web), so I feel like a solid response could be very useful to a lot of people.
Sample data
Wednesday, August 1, 2018 12:00 AM 71.14
Thursday, August 2, 2018 12:00 AM 55.44
Friday, August 3, 2018 12:00 AM 50.09
Saturday, August 4, 2018 12:00 AM 45.81
Sunday, August 5, 2018 12:00 AM 43.27
Monday, August 6, 2018 12:00 AM 40.61
Tuesday, August 7, 2018 12:00 AM 39.38
Wednesday, August 8, 2018 12:00 AM 38.46
Thursday, August 9, 2018 12:00 AM 36.81
Friday, August 10, 2018 12:00 AM 35.94
with
user_first_event as (
select distinct id, min(timestamp)::date as first_event_date
from log
where
timestamp <= current_date
and timestamp >= {{start_date}} and timestamp <= {{end_date}}
group by id),
event as (
select distinct id, timestamp::date as user_event_date
from log
where timestamp <= current_date and timestamp >= {{start_date}}),
gap as (
select
user_first_event.id,
user_first_event.first_event_date,
event.user_event_date,
event.user_event_date - user_first_event.first_event_date as days_since_signup
from user_first_event
join event on user_first_event.id = event.id
where user_first_event.first_event_date <= event.user_event_date),
conversion_rate as (
select
first_event_date,
(sum(case when days_since_signup = 7 then 1 else 0 end) * 100.0 /
count(distinct id)
) as seven_day_retention_rate
from gap
group by first_event_date
)
SELECT first_event_date,
AVG(seven_day_retention_rate)
OVER(ORDER BY first_event_date ROWS BETWEEN 29 PRECEDING AND CURRENT ROW) AS rolling_avg_retention_rate
FROM conversion_rate
The problem is a bit easier than your query makes it seem, you can actually do it with just one subquery and one out query as follows:
select first_event_date
, avg(seven_day_return) as seven_day_return_day_only
, avg( avg(seven_day_return) ) OVER(ORDER BY first_event_date asc ROWS BETWEEN 29 preceding AND CURRENT ROW ) AS thirty_day_rolling_retention
from (
--inner query to get value for user, 1 if they retain and 0 if they do not
select min(timestamp)::date as first_event_date
, case when array_agg(timestamp::date) #> ARRAY[ (min(timestamp)::date + 7) ] then 1 else 0 end as seven_day_return
from log
group by id ) t
group by t.first_event_date;
Note that this weights each day equally rather than each user equally across days. If you want to weight the average by user across days then you can update the outer calculation using more aggregates and windows to compute the value with weightings.
Reference: http://sqlfiddle.com/#!17/ee17e/1/0
If you don't have access to array_agg (but have access to window functions) you can use:
select first_event_date
, avg(seven_day_return) as day_seven_day_return
, avg( avg(seven_day_return) ) OVER(ORDER BY first_event_date asc ROWS BETWEEN 29 preceding AND CURRENT ROW ) AS thirty_day_rolling_retention
from (
--inner query to get value for user
select min(timestamp)::date as first_event_date
, case when exists(select 1 from log l2 where l2.id = log.id and l2.timestamp::date = min(log.timestamp)::date + 7) then 1 else 0 end as seven_day_return
from log
group by id ) t
group by t.first_event_date;
Currently I need to send an Email to all users that have 5 days with their payment due_date expired and are status=1 (pending to pay) for the current month and year because they might have future dates or past dates. example
due_date= 27/06/2018 send email after 5 days 1/05/2018
my Query to grab all users with a interval within 5 days is the following:
SELECT payments_payment.id, payments_payment.due_date
FROM payments_payment
WHERE payments_payment.due_date < NOW() - '5 day'::interval
AND payments_payment.status = 1
AND EXTRACT(year FROM payments_payment.due_date) = EXTRACT(year FROM NOW())
AND EXTRACT(month FROM payments_payment.due_date) = EXTRACT(month FROM NOW())
ORDER BY payments_payment.due_date ASC;
Need to make a different approach since the question is inverse for that reason I need to get the difference between 2 dates and see if it matches my day limit here is the Query.
PostgreSQL Query:
SELECT due_date
FROM payments_payment
WHERE payments_payment.due_date + interval '5 day' < current_date
AND payments_payment.status = 1
Explanation
Get all payment dates where status equals 1 and month equals current month and year where the due_date substracted by current date is equals to 5 days.
I got the information I needed from my last post about Postgres: Defining the longest streak (in days) per developer.
However now I want know the longest streak per developer regardless of Saturdays or Sundays. For instance, Bob worked from Thursday 18, Friday 19, Monday 22 and Tuesday 23, hence Bob streak is 4 days.
I understand I can use the DOW window function, which gives me 0 as Sunday , 1 Monday and so on. But
I don’t see how I can apply DOW function in the last solution proposed by Gordon Linoff.
Can some of you help me in this matter? Cheers,
WITH
working_limits AS (
SELECT
MIN(mr_date) AS start_date,
MAX(mr_date) AS end_date
FROM
xxx
),
working_days AS (
SELECT
ROW_NUMBER() OVER () AS day_number,
s.d::date AS date
FROM
GENERATE_SERIES((SELECT start_date FROM working_limits),
(SELECT end_date FROM working_limits),
'1 day') AS s(d)
WHERE
EXTRACT(dow FROM s.d) BETWEEN 1 AND 5),
worked_days AS (
SELECT
ROW_NUMBER() OVER () AS day_number,
developer,
mr_date AS date
FROM
xxx
ORDER BY
developer,
mr_date
)
SELECT
y.developer,
MAX(y.days)
FROM (
SELECT
x.developer,
COUNT(*) AS days
FROM (
SELECT
wngd.date,
wd.developer,
wngd.day_number - wd.day_number AS delta
FROM
working_days wngd INNER JOIN worked_days wd
ON
wngd.date = wd.date) AS x
GROUP BY
x.developer,
x.delta) AS y
GROUP BY
y.developer;