Cita:
Empezado por bucanero
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".