Skip to content
Advertisement

Is there a better way to execute this SQL query?

I have written this SQL query to get data for each customer in my database.

As you can see, I’m trying to get the total of unpaid orders and the total of orders to my query.

My goal at the end is to get only the users with unpaids orders (I think i will have to make it with a HAVING at the end of the query).

Here is my query

SELECT 
u.id, 
u.first_name, 
u.last_name, 
u.email, 
u.phone, 
(SELECT COUNT(*) FROM account_order WHERE account_order.user_id = u.id AND account_order.is_paid = False AND account_order.max_meals > 0) as total_not_paid,
(SELECT COUNT(*) FROM account_order WHERE account_order.user_id = u.id) AS total_orders
FROM account_user u

Do you believe there is a better way to get the records ?

How can I get the users with only one total_not_paid and only one total_order ?

Advertisement

Answer

If you want unpaid orders, you can use explicit aggregation and a having clause:

SELECT u.*,
       COUNT(*) FILTER (WHERE NOT is_paid AND ao.max_meals > 0) as total_not_paid,
       COUNT(*) AS total_orders
FROM account_user u JOIN
     account_order ao
     ON ao.user_id = u.id
GROUP BY u.id
HAVING COUNT(*) FILTER (WHERE NOT is_paid AND ao.max_meals > 0) > 0;
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement