Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Znajdź zakresy dat nakładające się w tej samej tabeli dla określonego użytkownika MySQL

Oto pierwsza część:Nakładające się samochody na użytkownika...

SQLFiddle — skorelowane zapytanie i połączenie zapytania

Część druga - więcej niż jeden użytkownik w jednym samochodzie jednocześnie:SQLFiddle - skorelowane zapytanie i dołączanie Zapytanie . Zapytanie poniżej...

Używam skorelowanych zapytań:

Prawdopodobnie będziesz potrzebować indeksów na identyfikator użytkownika i „samochód”. Jednak - sprawdź plan wyjaśnień, aby zobaczyć, w jaki sposób mysql uzyskuje dostęp do danych. I po prostu spróbuj :)

Nakładające się samochody na użytkownika

Zapytanie:

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`;      

Wyniki:

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

Dlaczego to działa? lub jak o tym myślę:

Używam skorelowanego zapytania, więc nie mam duplikatów, z którymi mogę sobie poradzić i prawdopodobnie jest to dla mnie najłatwiejsze do zrozumienia. Istnieją inne sposoby wyrażenia zapytania. Każdy ma zalety i wady. Chcę czegoś, co z łatwością zrozumiem.

Wymagania:Dla każdego użytkownika upewnij się, że nie ma dwóch lub więcej samochodów w tym samym czasie.

Tak więc dla każdego rekordu użytkownika (AllCars) sprawdź pełną tabelę (overlapCar), aby sprawdzić, czy możesz znaleźć inny rekord, który nakłada się na czas bieżącego rekordu. Jeśli go znajdziemy, wybierz bieżący rekord, który sprawdzamy (we wszystkich samochodach).

Dlatego nakładanie się czek to:

  • allCars userid i overLap userid musi być taki sam

  • allCars rekord samochodu i overlap rekord samochodu musi być inny

  • allCars zakres czasu i overLap zakres czasu musi się pokrywać.

    Sprawdzenie zakresu czasu:

    Zamiast sprawdzać, czy czasy się nakładają, użyj pozytywnych testów. Najłatwiejszym sposobem jest sprawdzenie, czy nie zachodzi na siebie, i zastosowanie NOT do niego.

Jeden samochód z więcej niż jednym użytkownikiem w tym samym czasie...

Zapytanie:

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`;

 

Wyniki:

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

Edytuj:

W związku z komentarzami @philipxy , dotyczącymi zakresów czasowych wymagających sprawdzenia „większego lub równego”, zaktualizowałem tutaj kod. Nie zmieniłem SQLFiddles .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Wyłączanie sprawdzania kluczy obcych w wierszu poleceń

  2. MySQL jaki jest maksymalny rozmiar bazy danych?

  3. ORDER BY data z datami przeszłymi po datach nadchodzących

  4. mysqldump tabela bez zrzucania klucza podstawowego

  5. Docker nie może połączyć się z niedziałającym kontenerem