Estoy intentando realizar una consulta que requiere una columna calculada mediante una subconsulta que pasa la referencia de fecha a través de una variable. No estoy seguro si no estoy "haciendo las cosas bien", pero esencialmente la consulta nunca termina y gira durante minutos. Esta es mi consulta:Subconsulta de MySQL con variables definidas por el usuario
select @groupdate:=date_format(order_date,'%Y-%m'), count(distinct customer_email) as num_cust,
(
select count(distinct cev.customer_email) as num_prev
from _pj_cust_email_view cev
inner join _pj_cust_email_view as prev_purch on (prev_purch.order_date < @groupdate) and (cev.customer_email=prev_purch.customer_email)
where cev.order_date > @groupdate
) as prev_cust_count
from _pj_cust_email_view
group by @groupdate;
subconsulta tiene una inner join
realiza la autocombinación que sólo me da el número de los que han adquirido antes de la fecha en @groupdate
. El EXPLAIN
es a continuación:
+----+----------------------+---------------------+------+---------------+-----------+---------+---------------------------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+----------------------+---------------------+------+---------------+-----------+---------+---------------------------+--------+---------------------------------+
| 1 | PRIMARY | _pj_cust_email_view | ALL | NULL | NULL | NULL | NULL | 140147 | Using temporary; Using filesort |
| 2 | UNCACHEABLE SUBQUERY | cev | ALL | IDX_EMAIL | NULL | NULL | NULL | 140147 | Using where |
| 2 | UNCACHEABLE SUBQUERY | prev_purch | ref | IDX_EMAIL | IDX_EMAIL | 768 | cart_A.cev.customer_email | 1 | Using where |
+----+----------------------+---------------------+------+---------------+-----------+---------+---------------------------+--------+---------------------------------+
y la estructura de la tabla _pj_cust_email_view
es como tal:
'_pj_cust_email_view', 'CREATE TABLE `_pj_cust_email_view` (
`order_date` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
`customer_email` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
KEY `IDX_EMAIL` (`customer_email`),
KEY `IDX_ORDERDATE` (`order_date`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1'
Una vez más, como he dicho antes, no estoy realmente seguro de que esta es la mejor manera de lograr esto Cualquier crítica, dirección es apreciada!
actualización
que he hecho un pequeño progreso, y ahora estoy haciendo lo anterior procesalmente por iteración a través de todos los meses conocidas en lugar de meses en la base de datos y el establecimiento de los VARs antes de tiempo. No me gusta esto todavía. Esto es lo que tengo ahora:
establece el usuario definido vars
set @startdate:='2010-08', @enddate:='2010-09';
Obtiene mensajes de correo electrónico distintas totales en el rango dado
select count(distinct customer_email) as num_cust
from _pj_cust_email_view
where order_date between @startdate and @enddate;
Obtiene el recuento total de clientes que compraron antes del rango dado
select count(distinct cev.customer_email) as num_prev
from _pj_cust_email_view cev
inner join _pj_cust_email_view as prev_purch on (prev_purch.order_date < @startdate) and (cev.customer_email=prev_purch.customer_email)
where cev.order_date between @startdate and @enddate;
Donde @startdate
está configurado al principio del mes y @enddate
indica el final del rango de ese mes.
Realmente siento que esto se puede hacer en una consulta completa.
véase la actualización anterior para la solución actual que devuelve lo que estoy buscando, pero de manera iterativa y me gustaría que estuviera en una consulta completa. – philwinkle
Ayudaría si proporcionó algunos datos de entrada de muestra y algunos resultados esperados. – Thomas