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

Jak zwrócić brakujące wiersze w tabeli - Zgłoszenie nieobecności pracownika

Jeśli „nieobecność” jest zdefiniowana jako brak wiersza w emp_tx tabela dla konkretnego empcode dla określonej daty (data=północ do północy 24-godzinny okres) i ...

Jeśli dopuszczalne jest nie pokazywanie "nieobecności" dla daty, gdy nie ma żadnych transakcji w emp_tx tabela dla tej daty (tj. wyklucz datę, w której WSZYSTKIE empcode są nieobecne w tym dniu), a następnie ...

Możesz uzyskać pierwsze cztery kolumny określonego zestawu wyników za pomocą zapytania takiego:(nieprzetestowane)

SELECT m.empcode     AS `EmpCode` 
     , m.name        AS `EmpName`
     , m.dept        AS `Department`
     , d.dt          AS `AbsentDate`
  FROM ( SELECT DATE(t.s_date) AS dt
           FROM emp_tx t
          WHERE t.s_date >= '2012-12-12' 
            AND t.s_date < DATE_ADD( '2012-12-20' ,INTERVAL 1 DAY)
          GROUP BY DATE(t.s_date)
          ORDER BY DATE(t.s_date)
       ) d
 CROSS
  JOIN master m
  LEFT
  JOIN emp_tx p
    ON p.s_date >= d.dt
   AND p.s_date <  d.dt + INTERVAL 1 DAY
   AND p.empcode = m.empcode
 WHERE p.empcode IS NULL
 ORDER
    BY m.empcode
     , d.dt

Pobieranie piątej kolumny TotalNoofAbsent zwrócone w tym samym zestawie wyników jest możliwe, ale spowoduje to, że zapytanie będzie naprawdę nieuporządkowane. Ten szczegół może być efektywniej obsługiwany po stronie klienta podczas przetwarzania zwróconego zestawu wyników.

Jak działa zapytanie

Widok wbudowany aliasem d otrzymuje zestaw wartości "dat", które sprawdzamy. Korzystanie z emp_tx tabela jako źródło tych wartości „daty” jest wygodnym sposobem na zrobienie tego. Nie DATE() funkcja zwraca tylko część "daty" argumentu DATETIME; używamy GROUP BY aby uzyskać odrębną listę dat (tj. bez zduplikowanych wartości). (W przypadku tego zapytania wbudowanego widoku szukamy odrębnego zestawu wartości DATE między dwiema wartościami przekazanymi jako argumenty. Istnieją inne, bardziej skomplikowane sposoby generowania listy wartości DATE).

Tak długo, jak każda wartość „data”, którą uznasz za „nieobecność”, pojawi się gdzieś w tabeli (to znaczy, co najmniej jeden empcode miał jedną transakcję w każdym interesującym dniu) i tak długo, jak liczba wierszy w emp_tx tabela nie jest nadmierna, wtedy zapytanie wbudowanego widoku będzie działać dość dobrze.

(UWAGA:zapytanie w widoku wbudowanym można uruchomić osobno, aby sprawdzić, czy wyniki są poprawne i zgodne z oczekiwaniami.)

Następnym krokiem jest wykonanie wyników z widoku wbudowanego i wykonanie CROSS JOIN operacja (w celu wygenerowania produktu kartezjańskiego) pasująca do KAŻDEGO empcode z KAŻDĄ date zwrócone z widoku wbudowanego. Wynik tej operacji reprezentuje każde możliwe wystąpienie „obecności”.

Ostatnim krokiem w zapytaniu jest wykonanie operacji „anti-join” przy użyciu LEFT JOIN i WHERE IS NULL orzec. LEFT JOIN (złączenie zewnętrzne) zwraca każde możliwe wystąpienie obecności (od lewej strony), WŁĄCZNIE z tymi, które nie mają pasującego wiersza (rekordu obecności) z emp_tx tabela.

„Sztuczka” polega na dołączeniu predykatu (w klauzuli WHERE), który odrzuca wszystkie wiersze, w których znaleziono pasujący rekord obecności, tak aby pozostały tylko wszystkie kombinacje empcode i date (możliwe wystąpienia obecności), gdy nie było transakcji obecności NIE DOPASOWANE.

(UWAGA:Celowo pozostawiłem odniesienia do kolumny s_date (DATETIME) jako „puste” w predykatach i użyłem predykatów zakresu. Pozwoli to MySQL na efektywne wykorzystanie odpowiedniego indeksu, który zawiera tę kolumnę.)

Gdybyśmy mieli zawinąć odwołania do kolumn w predykaty wewnątrz funkcji, np. DATE(p.s_date) , wtedy MySQL nie będzie w stanie efektywnie wykorzystać indeksu w s_date kolumna.

Jak wskazuje jeden z komentarzy (do Twojego pytania), nie rozróżniamy transakcji, które oznaczają pracownika jako „przychodzące” lub „wychodzące”. Szukamy TYLKO istnienia transakcji dla tego kodu empcode w określonym 24-godzinnym okresie „od północy do północy”.

Istnieją inne podejścia do uzyskania tego samego zestawu wyników, ale wzorzec „anty-łączenia” zwykle okazuje się zapewniać najlepszą wydajność przy dużych zestawach.

Aby uzyskać najlepszą wydajność, prawdopodobnie będziesz potrzebować pokrycia indeksów:

... ON master (empcode, name, dept)

... ON emp_tx (s_date, empcode)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Co oznacza / dzieje się, gdy używasz `INNER JOIN` z wieloma instrukcjami tabeli bazy danych?

  2. Przechowywanie zawartości tablicy PHP w bazie danych MySQL

  3. Instalacja MySQL:BŁĄD:Nie udało się zbudować natywnego rozszerzenia gem

  4. Konwertuj wiersz sql na kolumny

  5. PHP i Checkboxy zaznaczają idą do tabeli