I have a service in which customers can open a "customer service ticket" which is charged. Whenever they do, they can open how many more "customer service tickets" they want for the next 30 days without being charged; and after that period if they open a ticket again they will be charged again (and if that happens, they will have another 30 days of free customer service).
Based on that, I have a table called customer_service_ticket in which I store each ticket with its date on "date" column.
What query gets all tickets which are chargeable, that is, these tickets that open the 30 days windows (and not tickets inside them)?
Eg. If the tickets have the dates
3/jan – 4/jan – 8/jan – 30/jan – 4/fev – 20/fev – 20/mar
the query should only return
3/jan – 4/fev – 20/mar.
Because every statement is applied to all lines, I couldn’t find a solution. I am working on a recursive CTE.
2
Answers
You’re absolutely right; using recursive CTE might be a bit overcomplicated for this particular scenario. Instead, a combination of window functions and subqueries can efficiently achieve the desired result. The approach involves identifying the start date of each 30-day window and selecting only those tickets.
Assuming your table is named customer_service_ticket and includes columns such as ticket_id and date, the following query should provide the desired output:
This query returns the dates of customer service tickets that mark the beginning of a new 30-day period, during which customers can open additional "customer service tickets" without being charged.
A recursive CTE is required for this type of problem because the selected rows are dependent on prior selected rows.
The following demonstrates a query that performs the requested operation:
Results:
The query begins by establishing example data as
tickets
(this would be an actual table for production use). The number of support days is defined inparms
. This allows the query to be more DRY (Don’t Repeat Yourself).The recursive CTE is found in
charged_tickets
. The initialization section determines the first charged ticket for each customer and the next date that charges will again apply. The iterative part performs the same operatiion for each successive charged ticket. The subqueries incharged_tickets
are necessary because PostgreSQL doesn’t supportDISTINCT ON
directly in recursive subqueries.