It should work, but it's really really ugly coding.
It requires that the DB server return *ALL THE ROWS* to PHP just so PHP can count them! Talk about overkill on data transfer.
Do the counting in MySQL, so you don't have to transfer all the data to PHP!
No, I take that back! Your first query is wrong. Because you do the GROUP BY, you will *NOT* be getting *ALL* orders. You will only be getting the number of *customers*.
Let's kill all that and start over. And let's keep PHP out of the mix.
Code:
SELECT COUNT(*) AS totalOrders
FROM orders
WHERE status='C'
AND orders.timestamp BETWEEN '$from' AND '$to'
short and sweet and simple.
Code:
SELECT COUNT(X.*) AS totalRepeatCustomers
FROM ( SELECT email, COUNT(*) as ordersPerEmail
FROM orders
WHERE status='C'
AND orders.timestamp BETWEEN '$from' AND '$to'
GROUP BY email
HAVING COUNT(*) > 1 ) AS X
Now execute those queries, read the one and only value returned by MySQL to PHP, and do your division.
We could even do the division in SQL code, so you'd only need one query. But it's probably not worth the effort, since we'd have to do essentially the same as both the above and wrap it all up in a big ugly query.