Reputation: 330
I'm struggling with how I can get a report of new customers each week (those who have never ordered previously). The results should look as follows:
WEEK_ENDING_DATE NEW_CUSTOMERS
---------------- -------------
2019-02-03 50
2019-02-10 60
My query does a Right Outer Join of old_orders and new_orders to find new customers (see query below).
I also have a helper table called my_calendars that helps me to group by week_end_date. The my_calendars table has rows containing each date in the year, the corresponding week_begin_date and week_end_date for that date. For example, for a date like 2019-02-15, the week_begin_date is 2019-02-11 and week_end_date is 2019-02-17 (Week is Mon - Sun, Format = YYYY-MM-DD). The helper table looks as follows:
DATE WEEK_BEGIN_DATE WEEK_END_DATE
---------- ---------------- -------------
2019-02-15 2019-02-11 2019-02-17
2019-01-08 2019-01-07 2019-01-13
Now, back to my query. I want to be able to find new customers each week. The problem I'm having is that I can't figure out how to place each week of the year in the query so as to compare the order dates. The old_orders are orders that took place before 'this week', and the new_orders are those that took place 'this week'. The query works fine when I use static dates, but I'm struggling to make the dates variable i.e. each week in the year. See my questions in the query where I'm having challenges.
SELECT
new_orders.week_end_date
,COUNT(DISTINCT new_orders.customer) AS new_customers
FROM
(SELECT *
FROM orders old
INNER JOIN my_calendar cal ON cal.date = old.order_date
#The line below works, but it's a static date of Feb 4. How do I replace it with each week in the calendar
WHERE cal.week_end_date < '2019-02-04'
#The commented line below does not work
#WHERE cal.date < cal.week_end_date
) AS old_orders
RIGHT OUTER JOIN (SELECT *
FROM order_items_view new
INNER JOIN my_calendar cal ON cal.date = new.order_date
#How do I replace the static dates below and compare with each week in the calendar
WHERE cal.date BETWEEN '2019-02-04' and '2019-02-10'
#The commented line below didn't work
#WHERE cal.week_end_date = cal.week_end_date
) AS new_orders
ON new_orders.customer = old_orders.customer
WHERE old_orders.customer IS NULL
GROUP BY new_orders.week_end_date
Upvotes: 0
Views: 336
Reputation: 222482
I would first use an aggregated subquery to compute the first order date of each customer, and then join the result with the calendar table :
SELECT
c.week_end_date,
COUNT(o.customer) AS new_customers
FROM
my_calendar AS c
LEFT JOIN (
SELECT customer, MIN(order_date) first_order_date
FROM orders
GROUP BY customer
) AS o ON c.date = o.first_order_date
GROUP BY c.week_end_date
Upvotes: 1