Note: Please test it carefully and use it as you wish. I couldn't find an easy query for it. I don't guarantee to work for all cases :) If you just want the answer, the complete query is shown in the end.
The goal is that I'll try to get a table with start and end dates in one row, and then I'll simply calculate average difference between two dates. Something like this.
id | account_id | account_name | start_date | end_date
------------------------------------------------------------
1 | 342 | Kent Brewery | 2015-09-12 | 2015-10-12
2 | 342 | Kent Brewery | 2015-10-12 | 2015-11-12
3 | 342 | Kent Brewery | 2015-11-12 | 2015-12-12
4 | 555 | Acme Fireworks | 2015-06-15 | 2015-09-15
5 | 555 | Acme Fireworks | 2015-09-15 | 2015-12-15
I'll create few temporary tables to make it a bit more clear. First query for start_date:
QUERY:
create temporary table uniq_start_dates
select (@sid := @sid + 1) id, tmp_uniq_start_dates.*
from
(select distinct o1.account_id, o1.account_name, o1.order_date start_date
from orders o1
join orders o2 on o1.account_id=o2.account_id and o1.order_date < o2.order_date
order by o1.account_id, o1.order_date) tmp_uniq_start_dates
join (select @sid := 0) AS sid_generator
OUTPUT: temporary table - uniq_start_dates
id | account_id | account_name | start_date
-----------------------------------------------
1 | 342 | Kent Brewery | 2015-09-12
2 | 342 | Kent Brewery | 2015-10-12
3 | 342 | Kent Brewery | 2015-11-12
4 | 555 | Acme Fireworks | 2015-06-15
5 | 555 | Acme Fireworks | 2015-09-15
Do the same thing for end_date:
QUERY:
create temporary table uniq_end_dates
select (@eid := @eid + 1) id, tmp_uniq_end_dates.*
from
(select distinct o2.account_id, o2.account_name, o2.order_date end_date
from orders o1
join orders o2 on o1.account_id=o2.account_id and o1.order_date < o2.order_date
order by o2.account_id, o2.order_date) tmp_uniq_end_dates
join (select @eid := 0) AS eid_generator
OUTPUT: temporary table - uniq_end_dates
id | account_id | account_name | end_date
-----------------------------------------------
1 | 342 | Kent Brewery | 2015-10-12
2 | 342 | Kent Brewery | 2015-11-12
3 | 342 | Kent Brewery | 2015-12-12
4 | 555 | Acme Fireworks | 2015-09-15
5 | 555 | Acme Fireworks | 2015-12-15
If you notice, I created new auto id for each view so that I can join them back to one table (like the very first table). Let's join uniq_start_dates and uniq_end_dates.
QUERY:
create temporary table uniq_start_end_dates
select uniq_start_dates.*, uniq_end_dates.end_date
from uniq_start_dates
join uniq_end_dates using (id)
OUTPUT: temporary table - uniq_start_end_dates
(the same one as the first table)
Now it's an easy part. Just aggregate and get average date time difference.
QUERY:
select account_id, account_name, avg(timestampdiff(day, start_date, end_date)) average_days
from uniq_start_end_dates
group by account_id, account_name
OUTPUT:
account_id | account_name | average_days
--------------------------------------------
342 | Kent Brewery | 30.3333
555 | Acme Fireworks | 91.5000
If you may notice, Plastic Inc. is not in the result. If you care about "null" average_days. Here it is:
QUERY:
select all_accounts.account_id, all_accounts.account_name, accounts_with_average_days.average_days
from
(select distinct account_id, account_name from orders) all_accounts
left join
(select account_id, account_name, avg(timestampdiff(day, start_date, end_date)) average_days
from uniq_start_end_dates
group by account_id, account_name) accounts_with_average_days
using (account_id, account_name)
OUTPUT:
account_id | account_name | average_days
--------------------------------------------
342 | Kent Brewery | 30.3333
555 | Acme Fireworks | 91.5000
900 | Plastic Inc. | null
Here is a complete messy query:
select all_accounts.account_id, all_accounts.account_name, accounts_with_average_days.average_days
from
(select distinct account_id, account_name from orders) all_accounts
left join
(select uniq_start_dates.account_id, uniq_start_dates.account_name, avg(timestampdiff(day, start_date, end_date)) average_days
from
(select (@sid := @sid + 1) id, tmp_uniq_start_dates.*
from
(select distinct o1.account_id, o1.account_name, o1.order_date start_date from orders o1
join orders o2 on o1.account_id=o2.account_id and o1.order_date < o2.order_date order by o1.account_id, o1.order_date) tmp_uniq_start_dates join (select @sid := 0) AS sid_generator
) uniq_start_dates
join
(select (@eid := @eid + 1) id, tmp_uniq_end_dates.*
from
(select distinct o2.account_id, o2.account_name, o2.order_date end_date from orders o1
join orders o2 on o1.account_id=o2.account_id and o1.order_date < o2.order_date order by o2.account_id, o2.order_date) tmp_uniq_end_dates join (select @eid := 0) AS eid_generator
) uniq_end_dates
using (id)
group by uniq_start_dates.account_id, uniq_start_dates.account_name) accounts_with_average_days
using (account_id, account_name)