Mam tabelę, która potencjalnie pomieści setki tysięcy liczb całkowitych
desc id_key_table;
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| id_key | int(16) | NO | PRI | NULL | |
+----------------+--------------+------+-----+---------+-------+
Z programu mam duży zestaw liczb całkowitych. Chciałbym zobaczyć, które z tych liczb całkowitych NIE znajdują się w powyższej kolumnie id_key.
Do tej pory wymyśliłem następujące podejścia:
1) Iteruj przez każdą liczbę całkowitą i wykonaj:
select count(*) count from id_key_table where id_key = :id_key
Gdy liczba wynosi 0, brak identyfikatora w tabeli.
To wydaje się okropnym, okropnym sposobem na zrobienie tego.
2) Utwórz tabelę tymczasową, wstaw każdą z wartości do tabeli tymczasowej i wykonaj JOIN na dwóch tabelach.
create temporary table id_key_table_temp (id_key int(16) primary key );
insert into id_key_table_temp values (1),(2),(3),...,(500),(501);
select temp.id_key
from id_key_table_temp temp left join id_key_table as main
on temp.id_key = main.id_key
where main.killID is null;
drop table id_key_table_temp;
Wydaje się to najlepszym podejściem, ale jestem pewien, że istnieje o wiele lepsze podejście, o którym jeszcze nie myślałem. Wolałbym nie tworzyć tabeli tymczasowej i używać jednego zapytania do ustalenia, które liczby całkowite brakuje.
Czy istnieje odpowiednie zapytanie dla tego typu wyszukiwania?
(MySQL)
Odpowiedzi:
Twoje drugie rozwiązanie z LEFT JOIN jest zdecydowanie najlepszym podejściem. Nie użyłbym tabeli tymczasowej, użyłbym zwykłej tabeli i zapełniłbym ją nowymi wartościami za każdym razem, gdy chcesz uruchomić zapytanie.
źródło
Wygląda na to, że „duży zestaw liczb całkowitych” jest wciąż znacznie mniejszy niż tabela z „setkami tysięcy liczb całkowitych”. Przy takim założeniu i chyba że w MySQL istnieje sposób na użycie tablicy liczb całkowitych jako tabeli w instrukcji SQL, druga opcja jest prawdopodobnie najlepsza. Powinien wykonać pełne skanowanie tabeli tymczasowej i indeksu na głównej tabeli. Główną zaletą jest to, że musi tylko zeskanować indeks zawierający setki tysięcy liczb całkowitych za jednym razem i musi tylko wysłać klientowi wyniki. Twoje zapytanie może (ale nie musi) zostać przepisane w następujący sposób:
źródło
Zamiast tabeli tymczasowej i wstawiania za pomocą
insert into id_key_table_temp values (1),(2),(3),...,(500),(501);
, możesz utworzyć podzapytanie ze wszystkimi wartościami, które próbujesz sprawdzić:źródło
Jak zauważono w moim komentarzu, jest to prawdopodobnie bardziej odpowiednie dla przepływu stosu. Myślę jednak, że oba te rozwiązania nie są najlepsze:
Rozwiązanie 1 wymaga wielu połączeń Select, bardzo nieefektywnych
Rozwiązanie 2 jest lepsze, ale nie jestem pewien, czy koszt wprowadzenia tak wielu wartości jest najlepszym rozwiązaniem.
Możliwym rozwiązaniem 3 byłoby utworzenie jednego zapytania:
i programowo uzyskaj różnicę z zestawu liczb całkowitych i zawartości DB. W najgorszym przypadku (ponieważ jest dużo liczb całkowitych) Ta trasa powinna być lepsza niż Rozwiązanie 1. Rozwiązanie 2 może również zwrócić wiele liczb całkowitych (jeśli tabela zawiera grupę, której nie ma w zestawie danych), więc zależy ™!
źródło
Prawie to rozwiązałem w StackOverflow , ale chciałbym rozwinąć więcej informacji na temat korzystania z tabeli permanent temp (PermTemp). ( stała temperatura, czy to nie oksymoron ?)
W StackOverflow miałem procedurę składowaną test.CreateSampleTable i test.GetMissingIntegers utwórz tabelę próbek, a następnie utwórz dynamiczną tabelę temp do wypełnienia przed wykonaniem dużego JOIN w celu znalezienia różnic.
Tym razem stwórzmy przykładową tabelę wraz ze stałą tabelą.
Oto test.LoadSampleTables:
Po uruchomieniu tego oto tabele i ich zawartość:
Oto wyzwalacze dla tabeli PermTemp
Teraz zaimportujmy nową partię rekordów, test tabeli. Tydzień_batch, niektóre klucze używane wcześniej, inne klucze klapsy nowe:
Weźmy test.weekly_batch i bezpiecznie połączmy go w test.id_key_table_keys i utwórz tabelę test.new_keys_to_load:
Oto wynik:
Od tego momentu po prostu użyj tabeli new_keys_to_load jako listy marek z nowymi kluczami do zaimportowania. Ponieważ new_keys_to_load jest mniejszy niż tabela PermTemp, zawsze powinieneś używać new_keys_to_load po lewej stronie LEFT JOIN.
źródło