Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

Seleccionar rango de fechas de a 1 minuto

Estas en el tema de Seleccionar rango de fechas de a 1 minuto en el foro de Mysql en Foros del Web. Hola gente lo que quiero hacer (nose si se podra) es seleccionar entre dos fechas dadas, de tipo datetime, seleccionar todos los minutos que hay ...
  #1 (permalink)  
Antiguo 03/07/2014, 22:59
Avatar de NSD
NSD
Colaborador
 
Fecha de Ingreso: mayo-2012
Ubicación: Somewhere
Mensajes: 1.332
Antigüedad: 11 años, 11 meses
Puntos: 320
Seleccionar rango de fechas de a 1 minuto

Hola gente lo que quiero hacer (nose si se podra) es seleccionar entre dos fechas dadas, de tipo datetime, seleccionar todos los minutos que hay entre ellos, por supuesto que por programacion es mucho mas facil, pero necesito que sea por sql porque al resultado lo tengo que meter en un join contra otra tabla.


A ver si me explico mejor con un ejemplo, supongamos que tengo estas dos fechas:

Código MySQL:
Ver original
  1. SET @fInicio = "2014-07-04 12:00:00";
  2. SET @fFinal  = "2014-07-04 12:10:00";

Lo que quiero hacer es un select que me devuelva:
2014-07-04 12:00:00
2014-07-04 12:01:00
2014-07-04 12:02:00
2014-07-04 12:03:00
2014-07-04 12:04:00
2014-07-04 12:05:00
2014-07-04 12:06:00
2014-07-04 12:07:00
2014-07-04 12:08:00
2014-07-04 12:09:00
2014-07-04 12:10:00

La forma mas rustica y artesanal es crear una tabla y poner ahi todos los posibles minutos del dia, pero quiza se pueda hacer solo en la consulta sin crear ninguna tabla
__________________
Maratón de desafíos PHP Junio - Agosto 2015 en FDW | Reglamento - Desafios
  #2 (permalink)  
Antiguo 04/07/2014, 06:57
Colaborador
 
Fecha de Ingreso: marzo-2008
Ubicación: Sabadell
Mensajes: 4.897
Antigüedad: 16 años, 1 mes
Puntos: 574
Respuesta: Seleccionar rango de fechas de a 1 minuto

Cita:
...que meter en un join contra otra tabla.
Contra la otra tabla

Código MySQL:
Ver original
  1. ...WHERE campo  BETWEEN '2014-07-04 12:00:00' AND '2014-07-04 12:10:00';

No te sirve?
__________________
Quim
--------------------------------------------------
Ayudar a ayudar es una buena práctica!!! Y da buenos resultados.
  #3 (permalink)  
Antiguo 04/07/2014, 07:09
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: Seleccionar rango de fechas de a 1 minuto

También podrías usar un
Código MySQL:
Ver original
  1. ...
  2. GROUP BY DATE(fecha), HOUR(fecha), MINUTE(fecha)
Ahora, bien, los minutos en los que no haya datos, los deberás crear programáticamente...
Usar una tabla con 1440 registros por cada día a considerar, me parece un despropósito innecesario.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #4 (permalink)  
Antiguo 04/07/2014, 10:00
Avatar de NSD
NSD
Colaborador
 
Fecha de Ingreso: mayo-2012
Ubicación: Somewhere
Mensajes: 1.332
Antigüedad: 11 años, 11 meses
Puntos: 320
Respuesta: Seleccionar rango de fechas de a 1 minuto

Cita:
Contra la otra tabla

Código MySQL:
Ver original
...WHERE campo BETWEEN '2014-07-04 12:00:00' AND '2014-07-04 12:10:00';


No te sirve?
Hola @quimfv gracias por responder pero no, no me sirve, necesito todos los minutos entre dos fechas como tabla para luego hacer el producto carteciano contra otra tabla.

@gnzsoloyo Gracias por la respuesta pero temo que tampoco me sirve, no estaba seguro de que con sql se pudiera, lo que habia pensado es crear una tabla con 1440 times y selecionar el concat de la fecha con el time asi solo tengo 1440 registros sino cada vez que varia la fecha tengo que repoblar la tabla y no tiene sentido.


Les explico cual es mi problema a resolver a ver si se les ocurre una forma de resolverlo diferente:

Tengo una tabla llamada agenda, que tiene estos campos:

id | hs_inicio (datetime) | hs_fin (datetime) | descripcion...

cada tarea en la agenda es un registro en esa tabla, lo que yo quiero saber, es entre dos fechas, que rangos de tiempos tengo libres tengo, esta es la consulta que uso ahora para saber que rangos tengo libres en el dia:

Código MySQL:
Ver original
  1. SET @dia = '2014-07-04';
  2.     SET @minFecha = CONCAT(@dia, ' 00:00:00');
  3.     SET @maxFecha = CONCAT(@dia, ' 23:59:00');
  4.     SET @inicio = @minFecha;
  5.     SET @fin = @maxFecha;
  6.     SET @inicioSig = @minFecha;
  7.     SET @lastId = 0;
  8.     SET @mostrar = FALSE;
  9.     SET @resto = 0;
  10.         DATE_FORMAT(IF(mostrar, inicio, resto_inicio), '%d/%m/%Y %H:%i:%s') AS inicio,
  11.         DATE_FORMAT(IF(mostrar, fin, resto_fin), '%d/%m/%Y %H:%i:%s') AS fin,
  12.         DATE_FORMAT(IF(mostrar, inicio, resto_inicio), '%Y-%m-%d %H:%i:%s') AS raw_inicio,
  13.         DATE_FORMAT(IF(mostrar, fin, resto_fin), '%Y-%m-%d %H:%i:%s') AS raw_fin,
  14.         TIMESTAMPDIFF(MINUTE, IF(mostrar, inicio, resto_inicio), IF(mostrar, fin, resto_fin)) AS minutos
  15.     FROM
  16.     (SELECT
  17.         IF(agd2.id = @lastId, (@mostrar:=TRUE), (@mostrar:=FALSE)) AS mostrar,
  18.         IF(@mostrar, 0, (@lastId:=agd2.id)) AS tmp1,
  19.         IF(@mostrar, @inicio,
  20.             IF
  21.             (agd2.`hs_inicio` > @inicio,
  22.                 IF((@fin:=agd2.`hs_inicio`) AND (@inicioSig:=agd2.`hs_fin`), TRUE, FALSE)
  23.             ,
  24.                 IF((@inicio:=agd2.`hs_fin`) AND (@fin:=agd2.`hs_fin`) AND (@inicioSig:=agd2.`hs_fin`), TRUE, FALSE)
  25.             )
  26.        
  27.         ) AS inicio,
  28.         @fin AS fin,
  29.         IF(@mostrar, (@inicio:=@inicioSig), @inicioSig) AS resto_inicio,
  30.         IF(@mostrar, (@fin:=@maxFecha), @maxFecha) AS resto_fin,
  31.         IF(@mostrar, -1, (@resto:=@resto+1)) AS resto_nro
  32.     FROM
  33.         `agenda` agd
  34.         JOIN  `agenda` AS agd2 -- Producto cartesiano
  35.     WHERE        
  36.         (
  37.                 (DATE_FORMAT(agd.`hs_inicio`, '%Y-%m-%d') = @dia)
  38.             OR  (DATE_FORMAT(agd.`hs_fin`, '%Y-%m-%d') = @dia)
  39.         )
  40.         AND
  41.         (
  42.                 (DATE_FORMAT(agd2.`hs_inicio`, '%Y-%m-%d') = @dia)
  43.             OR  (DATE_FORMAT(agd2.`hs_fin`, '%Y-%m-%d') = @dia)
  44.         )
  45.     ORDER BY
  46.         agd2.`hs_inicio`
  47.     )
  48.     AS tTemp
  49.     WHERE
  50.     (
  51.             tTemp.mostrar = 1
  52.         OR  tTemp.resto_nro = @resto
  53.     )
  54.     AND
  55.         inicio != fin
  56.     ORDER BY inicio ASC

Pero tiene varios problemas, por ejemplo, si una tarea empieza a la misma hora exacta que termina otra genera registros basura.

Si una tarea esta superpuesta con otra, genera cualquier cosa.

Solo funciona bien si las tareas estan separadas entre si y no superpuestas, lo cual no siempre es el caso.

Actualmente lo parcheo con programacion (se que es off-topic pero lo posteo para que vean que es lo que le corrijo para que ande bien)
Cita:
Editado: Código de programación no permitido en Foros de Bases de Dtos. Leer las normas del foro, por favor.
Se me ocurrio que si en otra tabla tengo todos los minutos del dia, luego podria hacer un join contra las tareas existentes para que solo me queden los minutos libres, y luego, volver a hacer un join contra si misma para buscar los rangos de minutos correlativos, pero nose si hay otra solucion
__________________
Maratón de desafíos PHP Junio - Agosto 2015 en FDW | Reglamento - Desafios

Última edición por gnzsoloyo; 04/07/2014 a las 10:14
  #5 (permalink)  
Antiguo 09/07/2014, 07:53
 
Fecha de Ingreso: julio-2014
Mensajes: 2
Antigüedad: 9 años, 9 meses
Puntos: 0
Respuesta: Seleccionar rango de fechas de a 1 minuto

Hola NSD, una forma rápida es utilizar una tally table o tabla de cuentas o números. Lo que haces es un join de tu tabla con la tally table con la condición el join. Esta tabla solo tiene una columna de valores incrementales y permite trabajarse muy bien. En
Cita:
Editado: Autopromo no permitida en FDW
podras ver un ejemplo, es este caso se utiliza una fecha inicio y una fecha fin para generar el respectivo rango de días contenidos, lo puedes ajustar para en vez de incrementar días lo haga con minutos.

Espero te sirva, saludos.

Última edición por gnzsoloyo; 09/07/2014 a las 08:05
  #6 (permalink)  
Antiguo 09/07/2014, 08:07
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: Seleccionar rango de fechas de a 1 minuto

@helibertoarias: Si tienes soluciones a proponer, postea las soluciones, es decir, el código o procedimiento propuesto para el problema.
No postees enlaces a páginas propias, porque eso transgrede las Políticas de uso de Foros del Web, y serán eliminadas sin aviso.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #7 (permalink)  
Antiguo 09/07/2014, 18:23
 
Fecha de Ingreso: julio-2014
Mensajes: 2
Antigüedad: 9 años, 9 meses
Puntos: 0
Respuesta: Seleccionar rango de fechas de a 1 minuto

Disculpas @gnzsoloyo, se me paso. Aquí comparto el código. Basicamente genero los dias contenidos en un rango de fechas sin uso de while, el principio es el mismo y puede aplicarse para horas y o minutos. Espero les sirva.

Código SQL:
Ver original
  1. CREATE DATABASE Demo
  2. GO
  3.  
  4. USE Demo
  5. GO
  6.  
  7. SET NOCOUNT ON
  8.  
  9. IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.TallyTable') AND TYPE IN (N'U'))
  10.     DROP TABLE dbo.TallyTable  
  11. GO
  12.  
  13. CREATE TABLE dbo.TallyTable(ID INT NOT NULL, PRIMARY KEY(ID))
  14.  
  15. GO
  16.  
  17. DECLARE @I INT = 0 /* Puede iniciar en 0 ó 1 según se desee*/
  18. DECLARE @IMax INT = 365*10 /*Para manejar operaciones de días con 10 años aproximadamente*/
  19.  
  20. WHILE @I<=@IMax
  21.     BEGIN
  22.         INSERT INTO dbo.TallyTable VALUES (@I)
  23.         SET @I=@I+1
  24.     END
  25.    
  26. USE Demo
  27. GO
  28.  
  29.  
  30.  
  31. IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'dbo.Hospedaje') AND TYPE IN (N'U'))
  32.     DROP TABLE dbo.Hospedaje    
  33. GO    
  34.  
  35. CREATE TABLE Hospedaje    (
  36.         HospedajeId INT NOT NULL IDENTITY(1,1),
  37.         Cliente VARCHAR(100) NOT NULL,
  38.         FechaIngreso DATE NOT NULL,
  39.         FechaEgreso DATE NOT NULL
  40.      )
  41.      
  42. INSERT INTO dbo.Hospedaje(
  43.           Cliente ,
  44.           FechaIngreso ,
  45.           FechaEgreso
  46.         )
  47.     SELECT 'PEKERMAN', ' 20140504', '20140507'
  48.    
  49. USE Demo
  50. GO
  51.      
  52. SELECT *, DATEADD(DAY, tt.id, h.FechaIngreso) Dia
  53.     FROM dbo.Hospedaje H
  54.         INNER JOIN dbo.TallyTable TT
  55.             ON DATEADD(DAY, tt.id, h.FechaIngreso)<= h.FechaEgreso
  56.     ORDER BY h.Cliente, tt.ID ASC

Los datos se verian algo así

  #8 (permalink)  
Antiguo 10/07/2014, 03:27
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 4 meses
Puntos: 2658
Respuesta: Seleccionar rango de fechas de a 1 minuto

Interesante, ahora bien ten en cuenta que ese script es para SQL Server, y no para MySQL...
Si lo intentas correr en MySQL no funcionará porque no reconocerá muchas cosas, desde la declaración de variables, algunos tipos de dato, los terminadores de sentencias, funciones propias de cada DBMS...
Habría que hacer una migración completa... y probablemente no funcione como script, sino que haya que implementarlo por medio de un stored procedure (las estructuras de interación como WHILE, por ejemplo, no funcionan en scripts en MySQL, solo en SP y SF).
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #9 (permalink)  
Antiguo 10/07/2014, 10:45
Avatar de NSD
NSD
Colaborador
 
Fecha de Ingreso: mayo-2012
Ubicación: Somewhere
Mensajes: 1.332
Antigüedad: 11 años, 11 meses
Puntos: 320
Respuesta: Seleccionar rango de fechas de a 1 minuto

Hola @helibertoarias gracias por la respuesta, si bien la solucion es para sql server, la migracion que menciona @gnzsoloyo es posible, pero el problema es el metodo que usas, estas creando una tabla auxiliar y la estas poblando con miles de registros, ten encuenta que yo necesito minutos no dias, asi que necesitaría 1440 registros por cada uno de los tuyos lo cual terminara en una tabla gigante que no sera una solucion definitiva ya que pasados 10 años o el tiempo especificado dejara de andar.

Seguire pensando otra alternativa ya la publicare aqui si la consigo
__________________
Maratón de desafíos PHP Junio - Agosto 2015 en FDW | Reglamento - Desafios

Etiquetas: join, rango, select, sql, tabla
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 03:15.