Aqui está a primeira parte:Carros sobrepostos por usuário...
SQLFiddle - consulta correlacionada e consulta de junção
Segunda parte - mais de um usuário em um carro ao mesmo tempo:SQLFiddle - consulta e associação correlacionadas Consulta . Consulta abaixo...
Eu uso as consultas correlacionadas:
Você provavelmente precisará de índices em userid e 'car'. No entanto - verifique o 'plano de explicação' para ver como o mysql está acessando os dados. E é só experimentar :)
Carros sobrepostos por usuário
A pergunta:
SELECT `allCars`.`userid` AS `allCars_userid`,
`allCars`.`car` AS `allCars_car`,
`allCars`.`From` AS `allCars_From`,
`allCars`.`To` AS `allCars_To`,
`allCars`.`tableid` AS `allCars_id`
FROM
`cars` AS `allCars`
WHERE
EXISTS
(SELECT 1
FROM `cars` AS `overlapCar`
WHERE
`allCars`.`userid` = `overlapCar`.`userid`
AND `allCars`.`tableid` <> `overlapCar`.`tableid`
AND NOT ( `allCars`.`From` >= `overlapCar`.`To` /* starts after outer ends */
OR `allCars`.`To` <= `overlapCar`.`From`)) /* ends before outer starts */
ORDER BY
`allCars`.`userid`,
`allCars`.`From`,
`allCars`.`car`;
Os resultados:
allCars_userid allCars_car allCars_From allCars_To allCars_id
-------------- ----------- ------------ ---------- ------------
1 Navara 2015-03-01 2015-03-31 3
1 GTR 2015-03-28 2015-04-30 4
1 Skyline 2015-04-29 2015-05-31 9
2 Aygo 2015-03-01 2015-03-31 7
2 206 2015-03-29 2015-04-30 8
2 Skyline 2015-04-29 2015-05-31 10
Por que funciona? ou Como eu penso sobre isso:
Eu uso a consulta correlacionada para não ter que lidar com duplicatas e provavelmente é a mais fácil de entender para mim. Existem outras maneiras de expressar a consulta. Cada um tem vantagens e desvantagens. Eu quero algo que eu possa entender facilmente.
Requisito:Para cada usuário garantir que ele não tenha dois ou mais carros ao mesmo tempo.
Assim, para cada registro de usuário (AllCars) verifique a tabela completa (overlapCar) para ver se você consegue encontrar um diferente registro que se sobrepõe à hora do registro atual. Se encontrarmos um, selecione o registro atual que estamos verificando (em todos os carros).
Portanto, a sobreposição cheque é:
-
oallCars
userid
e ooverLap
userid
deve ser o mesmo
-
oallCars
registro do carro e aoverlap
registro do carro deve ser diferente
-
oallCars
intervalo de tempo e ooverLap
intervalo de tempo deve se sobrepor.
A verificação do intervalo de tempo:
Em vez de verificar os tempos sobrepostos, use testes positivos. A abordagem mais fácil é verificar se não há sobreposição e aplicar umNOT
para isso.
Um carro com mais de um usuário ao mesmo tempo...
A pergunta:
SELECT `allCars`.`car` AS `allCars_car`,
`allCars`.`userid` AS `allCars_userid`,
`allCars`.`From` AS `allCars_From`,
`allCars`.`To` AS `allCars_To`,
`allCars`.`tableid` AS `allCars_id`
FROM
`cars` AS `allCars`
WHERE
EXISTS
(SELECT 1
FROM `cars` AS `overlapUser`
WHERE
`allCars`.`car` = `overlapUser`.`car`
AND `allCars`.`tableid` <> `overlapUser`.`tableid`
AND NOT ( `allCars`.`From` >= `overlapUser`.`To` /* starts after outer ends */
OR `allCars`.`To` <= `overlapUser`.`From`)) /* ends before outer starts */
ORDER BY
`allCars`.`car`,
`allCars`.`userid`,
`allCars`.`From`;
Os resultados:
allCars_car allCars_userid allCars_From allCars_To allCars_id
----------- -------------- ------------ ---------- ------------
Skyline 1 2015-04-29 2015-05-31 9
Skyline 2 2015-04-29 2015-05-31 10
Editar:
Em vista dos comentários, por @philipxy , sobre intervalos de tempo que precisam de verificações 'maior que ou igual a', atualizei o código aqui. Eu não mudei o
SQLFiddles
.