sql >> Databáze >  >> RDS >> Mysql

Najděte překrytí období ve stejné tabulce pro konkrétního uživatele MySQL

Zde je první část:Překrývající se auta na uživatele...

SQLFiddle – korelovaný dotaz a dotaz připojení

Druhá část – více než jeden uživatel v jednom autě současně:SQLFiddle – korelovaný dotaz a spojení Dotaz . Dotaz níže...

Používám korelované dotazy:

Pravděpodobně budete potřebovat indexy na userid a 'car'. Nicméně - zkontrolujte prosím 'vysvětlení plánu', abyste viděli, jak mysql přistupuje k datům. A prostě to zkuste :)

Překrývající se vozy na uživatele

Dotaz:

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

Výsledky:

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

Proč to funguje? nebo Jak o tom přemýšlím:

Používám korelovaný dotaz, takže nemám duplikáty, které bych řešil, a je pro mě pravděpodobně nejsnáze srozumitelný. Existují i ​​jiné způsoby vyjádření dotazu. Každá má výhody i nevýhody. Chci něco, čemu snadno porozumím.

Požadavek:U každého uživatele se ujistěte, že nemá dvě nebo více aut současně.

Takže pro každý uživatelský záznam (AllCars) zkontrolujte úplnou tabulku (overlapCar), abyste zjistili, zda nenajdete jiné záznam, který se překrývá v době aktuálního záznamu. Pokud nějaký najdeme, vyberte aktuální záznam, který kontrolujeme (v allCars).

Proto překrytí kontrola je:

  • allCars userid a overLap userid musí být stejné

  • allCars záznam vozu a overlap záznam vozu musí být jiný

  • allCars časový rozsah a overLap časový rozsah se musí překrývat.

    Kontrola časového rozsahu:

    Místo kontroly překrývajících se časů použijte pozitivní testy. Nejjednodušší přístup je zkontrolovat, zda se nepřekrývá, a použít NOT k tomu.

Jedno auto s více než jedním uživatelem současně...

Dotaz:

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

 

Výsledky:

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

Upravit:

S ohledem na komentáře od @philipxy o časových rozsazích vyžadujících kontroly „větší než nebo rovno“ jsem zde kód aktualizoval. Nezměnil jsem SQLFiddles .



  1. MariaDB CURRENT_ROLE() Vysvětleno

  2. Hekaton se zvratem:TVP v paměti – část 3

  3. Seskupit podle měsíce a roku v MySQL

  4. SET proměnná v příkazu SELECT - MySQL