2010-02-16 11 views
6

datos:cómo llevar los valores de todos los días en un mes

values date 
14 1.1.2010 
20 1.1.2010 
10 2.1.2010 
7 4.1.2010 
... 

muestra de consulta Acerca de January 2010 deberán tener 31 filas. Uno por cada día Y los valores se pueden agregar. Ahora mismo podría hacer esto con 31 consultas, pero me gustaría que esto funcione con una. ¿Es posible?

resultados:

1. 34 
2. 10 
3. 0 
4. 7 
... 
+0

Bienvenido a SO ivar. Creo que debe agregar más detalles sobre lo que está consultando y cómo. –

+0

Se necesitarían más detalles ... ¿qué idioma estás usando? ¿Qué sistema es este? – Mala

+0

¿Cuál es el tipo de columna de su fecha? ¿Es una FECHA o un VARCHAR? –

Respuesta

10

Esto es sorprendentemente difícil de hacer en SQL. Una forma de hacerlo es tener una larga declaración SELECT con UNION ONVOCATORIAS para generar los números del 1 al 31. Esto demuestra el principio pero se detuvo en 4 para mayor claridad:

SELECT MonthDate.Date, COALESCE(SUM(`values`), 0) AS Total 
FROM (
    SELECT 1 AS Date UNION ALL 
    SELECT 2 UNION ALL 
    SELECT 3 UNION ALL 
    SELECT 4 UNION ALL 
    -- 
    SELECT 28 UNION ALL 
    SELECT 29 UNION ALL 
    SELECT 30 UNION ALL 
    SELECT 31) AS MonthDate 
LEFT JOIN Table1 AS T1 
ON MonthDate.Date = DAY(T1.Date) 
AND MONTH(T1.Date) = 1 AND YEAR(T1.Date) = 2010 
WHERE MonthDate.Date <= DAY(LAST_DAY('2010-01-01')) 
GROUP BY MonthDate.Date 

Podría ser mejor usar una tabla para almacenar estos valores y unirse a ella en su lugar.

Resultado:

1, 34 
2, 10 
3, 0 
4, 7 
5

Teniendo en cuenta que para algunas fechas no tiene datos, tendrá que llenar los vacíos. Un enfoque para esto es tener una tabla de calendario llena con todas las fechas que necesita, y unirse contra eso. Si desea que los resultados muestren los números de día como lo ha mostrado en su pregunta, puede completarlos también en su calendario como etiquetas.

Uniría el campo de fecha de la tabla de datos al campo de fecha de la tabla de calendario, agrupará por ese campo y sumará los valores. Es posible que desee especificar límites para el rango de fechas cubiertas.

lo que podría tener:

CREATE TABLE Calendar (
    label varchar, 
    cal_date date, 
    primary key (cal_date) 
) 

Consulta:

SELECT 
    c.label, 
    SUM(d.values) 
FROM 
    Calendar c 
JOIN 
    Data_table d 
ON d.date_field = c.cal_date 
WHERE 
    c.cal_date BETWEEN '2010-01-01' AND '2010-01-31' 
GROUP BY 
    d.date_field 
ORDER BY 
    d.date_field 

actualización:

veo que tiene datetimes en lugar de fechas. Podrías simplemente usar la función MySQL DATE() en la unión, pero eso probablemente no sería óptimo. Otro enfoque sería tener tiempos de inicio y finalización en la tabla Calendario definiendo un 'intervalo de tiempo' para cada día.

0

Si estoy entendiendo la pregunta más bien vaga correctamente, usted quiere saber el número de registros para cada fecha dentro de un mes. Si eso es cierto, aquí es cómo puede hacerlo:

SELECT COUNT(value_column) FROM table WHERE date_column LIKE '2010-01-%' GROUP BY date_column 
+0

date_column no se ha configurado alguna vez – NineCattoRules

+1

@NineCattoRules A menos que sea el OP de hace siete años, no estoy seguro de cómo lo sabría. Si es el caso, la consulta puede modificarse fácilmente para ajustarse. – ceejayoz

+0

en la pregunta "... para cada día ..." y en "resultados" (de OP) hay '3. 0' – NineCattoRules

1

Para obtener dinámicamente las fechas dentro de un intervalo de fechas utilizando SQL se puede hacer esto (ejemplo en MySQL):

Crear una tabla para guardar los números del 0 al 9.

CREATE TABLE ints (i tinyint(4)); 

insert into ints (i) 
values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); 

ejecutar una consulta de este modo:

select ((curdate() - interval 2 year) + interval (t.i * 100 + u.i * 10 + v.i) day) AS Date 
from 
    ints t 
    join ints u 
    join ints v 
having Date between '2015-01-01' and '2015-05-01' 
order by t.i, u.i, v.i 

Esto generará todas las fechas entre 1 de enero de 2015 y 1 de mayo de 2015.

Output 
2015-01-01 
2015-01-02 
2015-01-03 
2015-01-04 
2015-01-05 
2015-01-06 
... 
2015-05-01 

La consulta se une a la tabla ints 3 veces y obtiene un número creciente (0 a 999). A continuación, agrega este número como un intervalo de días a partir de una fecha determinada, en este caso una fecha hace 2 años. Cualquier rango de fechas de hace 2 años y 1,000 días puede obtenerse con el ejemplo anterior. Para generar una consulta que genere fechas por más de 1,000 días, simplemente únase a la tabla de Ints una vez más para permitir hasta 10,000 días de rango, y así sucesivamente.

1

Esto funciona para mí ... Es una modificación de una consulta que encontré en otro sitio. La cláusula "INTERVALO 1 MES" garantiza que obtengo los datos del mes actual, incluidos los ceros de los días que no tienen aciertos. Cambie esto a "INTERVALO 2 MESES" para obtener los datos del último mes, etc.

Tengo una tabla llamada "carga útil" con una columna "marca de tiempo" - Estoy uniendo la columna de marca de hora a las fechas generadas dinámicamente, fundiéndola para que las fechas coincidan en la cláusula ON.


SELECT `calendarday`,COUNT(P.`timestamp`) AS `cnt` FROM 
(SELECT @tmpdate := DATE_ADD(@tmpdate, INTERVAL 1 DAY) `calendarday` 
    FROM (SELECT @tmpdate := 
     LAST_DAY(DATE_SUB(CURDATE(),INTERVAL 1 MONTH))) 
     AS `dynamic`, `payload`) AS `calendar` 
LEFT JOIN `payload` P ON DATE(P.`timestamp`) = `calendarday` 
GROUP BY `calendarday` 
Cuestiones relacionadas