Question

I want to calculate sum and count for only unique ids.

SELECT COUNT(orders.id), SUM(orders.total), SUM(orders.shipping) FROM "orders"
INNER JOIN "designer_orders" ON "designer_orders"."order_id" = "orders"."id" 
WHERE (designer_orders.state = 'pending' OR
       designer_orders.state = 'dispatched' OR
       designer_orders.state = 'completed')
  • Do this only for unique orders ids.
  • Add orders.total only if orders.id is unique. Same goes for shipping.
  • Avoid adding duplicates.

For example, orders table inner joined designer_orders table:

OrderId Total Some designer order column
 1       1000  2
 1       1000  3
 1       1000  5
 2       100   7
 3       133   8
 4       1000  10
 4       1000  20

In this case:

  • count of orders should be 4.
  • total of orders should be 2233.

Schema:

  • One order has many designer orders.
  • One designer order has only one order.
Was it helpful?

Solution

Try it this way

SELECT COUNT(o.id) no_of_orders, 
       SUM(o.total) total, 
       SUM(o.shipping) shipping 
  FROM orders o JOIN 
(
    SELECT DISTINCT order_id
      FROM designer_orders
     WHERE state IN('pending', 'dispatched', 'completed')
) d 
    ON o.id = d.order_id

Here is SQLFiddle demo

OTHER TIPS

Since you are only interested whether any row with qualifying status exists in the table designer_orders, the most obvious query style would be an EXISTS semi-join. Typically fastest with potentially many duplicate rows in n-table:

SELECT COUNT(o.id)     AS no_of_orders
      ,SUM(o.total)    AS total
      ,SUM(o.shipping) AS shipping
FROM   orders o
WHERE  EXISTS (
   SELECT 1
   FROM   designer_orders d
   WHERE  d.state = ANY('{pending, dispatched, completed}')
   AND    d.order_id = o.id
   );

-> SQLfiddle demo

For fast SELECT queries with bigger tables (and at some cost for write performance), you would have a partial index like:

CREATE INDEX designer_orders_order_id_idx ON designer_orders (order_id)
WHERE state = ANY('{pending, dispatched, completed}');

The index condition must match the WHERE condition of the query to talk the query planner into actually using the index.

A partial index is particularly attractive if there are many rows with a status that does not qualify. Else, an index without condition might be the better choice overall.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top