I have this work task, to write a SQL query that would show how many of the active customers are new (= do not have prior transactions) as opposed to returning per a given period.
There is nothing particular in the DB to get this, so my solution takes a transaction and compares customer_id
to the pool of customer_id
s that belong to all transactions that took place prior. Here's how it looks:
SELECT allthem.period, allthem.c "all", newonly.c "new", (allthem.c - newonly.c) "returning"
FROM (
SELECT date_trunc('week', t.paid::timestamptz) AS period, COUNT(DISTINCT(t.customer_id)) AS c
FROM transactions t
WHERE t.status = 'paid' AND (t.price->>'payment_total')::real > 35
GROUP BY date_trunc('week', t.paid::timestamptz)
ORDER BY date_trunc('week', t.paid::timestamptz) DESC) AS allthem
JOIN (
SELECT date_trunc('week', b.paid::timestamptz) AS period, COUNT(DISTINCT(t.customer_id)) AS c
FROM transactions t
WHERE t.status = 'paid' AND (t.price->>'payment_total')::real > 35
AND t.customer_id NOT IN (SELECT customer_id FROM transactions WHERE status='paid' AND (price->>'payment_total')::real > 35 AND paid::timestamptz < t.paid::timestamptz)
GROUP BY date_trunc('week', t.paid::timestamptz)
ORDER BY date_trunc('week', t.paid::timestamptz) DESC) AS newonly ON allthem.period=newonly.period
WHERE allthem.period > date_trunc('week', now()::timestamptz at time zone 'pst') - interval '12 months'
It works, but the problem is that it is quite slow.
Is there any way to compute the required data with less server load?