Ver Mensaje Individual
  #13  
Antiguo 22-09-2022
bucanero bucanero is offline
Miembro
 
Registrado: nov 2013
Ubicación: Almería, España
Posts: 208
Reputación: 11
bucanero Va camino a la fama
Cita:
Empezado por bucanero Ver Mensaje
En la respuesta que he dado anteriormente aparece el campo AID en la tabla, que incorpore para mis pruebas, este es de tipo AutonumericID para identificar de forma única cada registro y lo utilizo para que los LEFT JOIN no devuelvan el mismo registro que lo esta enlazando.


Código SQL [-]
SELECT `ini`.id,
ini.desde,
(
SELECT min(fin.hasta) AS hasta
FROM `fechas` fin
LEFT JOIN fechas ant
ON ant.id = fin.id
AND NOT (fin.desde = ant.desde AND fin.hasta = ant.hasta)
AND fin.hasta BETWEEN ant.desde AND ant.hasta
WHERE ant.id IS NULL
AND fin.id = ini.id
AND fin.`hasta` >= ini.hasta)
AS hasta
FROM `fechas` ini
LEFT JOIN fechas ant
ON ant.id = ini.id
AND NOT (ini.desde = ant.desde AND ini.hasta = ant.hasta)
AND ini.desde BETWEEN ant.desde AND ant.hasta
WHERE ant.id IS NULL
ORDER BY ini.id, ini.desde;

Como puse en mi respuesta a este mensaje y marco en rojo, el funcionamiento de este SQL era asumiendo que no habia otros registros con los mismos datos, en definitiva tenian un indice UNICO para los campos (id, desde, hasta).

Al aparecer ahora registros que si pueden contener los mismos datos, es el motivo por el que te aparecen duplicados en los resultados. Para solventar este caso basta con unas pequeñas modificaciones al SQL



Código SQL [-]
SELECT `ini`.id,
       ini.desde,
       (SELECT min(fin.hasta) AS hasta
          FROM `fechas` fin
               LEFT JOIN fechas sig
                  ON     sig.id = fin.id
                     AND fin.hasta BETWEEN sig.desde AND sig.hasta
                     AND (sig.hasta > fin.hasta)
         WHERE     sig.id IS NULL
               AND fin.id = ini.id
               AND fin.`hasta` >= ini.hasta)
          AS hasta
  FROM `fechas` ini
       LEFT JOIN fechas ant
          ON     ant.id = ini.id
             AND ini.desde BETWEEN ant.desde AND ant.hasta
             AND (ant.desde < ini.desde)
 WHERE ant.id IS NULL
GROUP BY ini.id, ini.desde
ORDER BY ini.id, ini.desde;


El principio de funcionamiento de este SQL sigue siendo igual,

* Para localizar el principio de bloque:

busca un registro donde su fecha "desde" o no este contenida en ningun otro registro, o si existe un registro donde si esta contenida, como mucho ambas fechas podran ser iguales, pero nunca la fecha del registro ant.desde puede ser anterior a la fecha del registro ini.desde.
* Para fin de bloque, ocurre exactamente lo mismo pero con los campos "hasta" en vez los campos "desde".
Responder Con Cita