intenta aplicar este código a su tarea -
CREATE TABLE visits(
user_id INT(11) NOT NULL,
dt DATETIME DEFAULT NULL
);
INSERT INTO visits VALUES
(1, '2011-06-30 12:11:46'),
(1, '2011-07-01 13:16:34'),
(1, '2011-07-01 15:22:45'),
(1, '2011-07-01 22:35:00'),
(1, '2011-07-02 13:45:12'),
(1, '2011-08-01 00:11:45'),
(1, '2011-08-05 17:14:34'),
(1, '2011-08-05 18:11:46'),
(1, '2011-08-06 20:22:12'),
(2, '2011-08-30 16:13:34'),
(2, '2011-08-31 16:13:41');
SET @i = 0;
SET @last_dt = NULL;
SET @last_user = NULL;
SELECT v.user_id,
COUNT(DISTINCT(DATE(dt))) number_of_days,
MAX(days) number_of_visits
FROM
(SELECT user_id, dt
@i := IF(@last_user IS NULL OR @last_user <> user_id, 1, IF(@last_dt IS NULL OR (DATE(dt) - INTERVAL 1 DAY) > DATE(@last_dt), @i + 1, @i)) AS days,
@last_dt := DATE(dt),
@last_user := user_id
FROM
visits
ORDER BY
user_id, dt
) v
GROUP BY
v.user_id;
----------------
Output:
+---------+----------------+------------------+
| user_id | number_of_days | number_of_visits |
+---------+----------------+------------------+
| 1 | 6 | 3 |
| 2 | 2 | 1 |
+---------+----------------+------------------+
Explicación:
Para entender cómo funciona vamos a ver la subconsulta, aquí está.
SET @i = 0;
SET @last_dt = NULL;
SET @last_user = NULL;
SELECT user_id, dt,
@i := IF(@last_user IS NULL OR @last_user <> user_id, 1, IF(@last_dt IS NULL OR (DATE(dt) - INTERVAL 1 DAY) > DATE(@last_dt), @i + 1, @i)) AS
days,
@last_dt := DATE(dt) lt,
@last_user := user_id lu
FROM
visits
ORDER BY
user_id, dt;
Como ve, la consulta devuelve todas las filas y realiza una clasificación para el número de visitas. Este es un método de clasificación conocido basado en variables, tenga en cuenta que las filas están ordenadas por los campos de usuario y fecha. Esta consulta calcula visitas de los usuarios, y salidas próximo conjunto de datos donde days
columna proporciona el rango para el número de visitas -
+---------+---------------------+------+------------+----+
| user_id | dt | days | lt | lu |
+---------+---------------------+------+------------+----+
| 1 | 2011-06-30 12:11:46 | 1 | 2011-06-30 | 1 |
| 1 | 2011-07-01 13:16:34 | 1 | 2011-07-01 | 1 |
| 1 | 2011-07-01 15:22:45 | 1 | 2011-07-01 | 1 |
| 1 | 2011-07-01 22:35:00 | 1 | 2011-07-01 | 1 |
| 1 | 2011-07-02 13:45:12 | 1 | 2011-07-02 | 1 |
| 1 | 2011-08-01 00:11:45 | 2 | 2011-08-01 | 1 |
| 1 | 2011-08-05 17:14:34 | 3 | 2011-08-05 | 1 |
| 1 | 2011-08-05 18:11:46 | 3 | 2011-08-05 | 1 |
| 1 | 2011-08-06 20:22:12 | 3 | 2011-08-06 | 1 |
| 2 | 2011-08-30 16:13:34 | 1 | 2011-08-30 | 2 |
| 2 | 2011-08-31 16:13:41 | 1 | 2011-08-31 | 2 |
+---------+---------------------+------+------------+----+
Luego grupo de este conjunto de datos por el usuario y utilizar funciones de agregado: 'COUNT (DISTINCT (FECHA (dt))) '- cuenta el número de días ' MAX (días) '- el número de visitas, es un valor máximo para el campo days
de nuestra subconsulta.
Eso es todo;)
En cuanto al primer aspecto ... Me parece que no puede entender por completo su sugerencia ... ¿Es posible para dar algunos detalles más? ¡Gracias! Respecto al segundo, mi consulta es correcta, siempre que no cuente el usuario y la ciudad, como se menciona en mi pregunta. – linkyndy
Lo siento, asumí que el resultado de "cuántos días ha estado un usuario en una ciudad" debería ser similar a (user_id, count_of_days). – Simon
Gracias por los detalles. Con varios ajustes para adaptarse a mi tabla de base de datos real, su consulta funciona como un encanto. ¡Gracias de nuevo! – linkyndy