Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Encontrar sobreposições de intervalo de datas na mesma tabela, para um usuário específico do MySQL


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 é:

  • o allCars userid e o overLap userid deve ser o mesmo

  • o allCars registro do carro e a overlap registro do carro deve ser diferente

  • o allCars intervalo de tempo e o overLap 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 um NOT 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 .