Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimizing MySQL query for fetching data using time range

Tags:

mysql

I'm building a line chart for a product sales report by using the Google Chart API and are separating the data on a per day basis with basically running the same query in a loop for each day using UNION ALL as glue.

E.g. A report for a whole year will repeat the query, using UNION ALL 365 times.

I'm guessing this is not a -best practice- example so if anyone would be so kind and point me in the right direction of how to optimize this query, I would greatly appreciate it.

  SELECT SUM(op.qty) AS qty
  FROM uc_order_products op
  LEFT JOIN uc_orders o ON o.order_id = op.order_id
  LEFT JOIN node n ON n.nid = op.nid
  LEFT JOIN node_type nt ON nt.type = n.type
  WHERE (o.created > 1247695200) AND (o.created < 1247781600)
  AND (o.order_status = 'completed')
  AND (nt.type = 'book' OR nt.type = 'digital_movie')

  UNION ALL 

  SELECT SUM(op.qty) AS qty
  FROM uc_order_products op
  LEFT JOIN uc_orders o ON o.order_id = op.order_id
  LEFT JOIN node n ON n.nid = op.nid
  LEFT JOIN node_type nt ON nt.type = n.type
  WHERE (o.created > 1247781600) AND (o.created < 1247868000)
  AND (o.order_status = 'completed')
  AND (nt.type = 'book' OR nt.type = 'digital_movie')

  UNION ALL

  SELECT SUM(.......

Thanks for all the quick replies! With the query example from jspcal, my query ended up like this:

  SELECT SUM(op.qty) AS qty, DATE_FORMAT(FROM_UNIXTIME(o.created),'%d-%m-%Y') AS day
  FROM uc_order_products op
  LEFT JOIN uc_orders o ON o.order_id = op.order_id
  LEFT JOIN node n ON n.nid = op.nid
  LEFT JOIN node_type nt ON nt.type = n.type
  WHERE (o.created > 1247695200) AND (o.created < 1263596400)
  AND (o.order_status = 'completed')
  AND (nt.type = 'book' OR nt.type = 'digital_movie')
  GROUP BY day

And with PHP, I combine a complete date range array (matching array keys with strtotime($data->day) from the query result) to get days with no sale.

like image 500
Borgenk Avatar asked Nov 15 '22 13:11

Borgenk


1 Answers

you can group by day:

select sum(op.qty) as qty, date_format(o.created, '%Y-%m-%d') as day
from ... where ... o.created >= subdate(now(), interval 1 year) and
o.created <= now() group by day order by day

will report the sum for each day of the year in the data set

like image 200
jspcal Avatar answered Dec 10 '22 03:12

jspcal