Ich habe eine Tabelle, in der möglicherweise Hunderttausende von Ganzzahlen gespeichert werden
desc id_key_table;
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| id_key | int(16) | NO | PRI | NULL | |
+----------------+--------------+------+-----+---------+-------+
Aus einem Programm habe ich eine große Menge von ganzen Zahlen. Ich würde gerne sehen, welche dieser Ganzzahlen NICHT in der obigen Spalte id_key stehen.
Bisher habe ich mir folgende Ansätze ausgedacht:
1) Durchlaufen Sie jede Ganzzahl und führen Sie Folgendes aus:
select count(*) count from id_key_table where id_key = :id_key
Wenn count 0 ist, fehlt der id_key in der Tabelle.
Dies scheint ein schrecklicher, schrecklicher Weg zu sein.
2) Erstellen Sie eine temporäre Tabelle, fügen Sie jeden der Werte in die temporäre Tabelle ein und führen Sie eine VERBINDUNG für die beiden Tabellen durch.
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;
Dies scheint der beste Ansatz zu sein, aber ich bin sicher, dass es einen weitaus besseren Ansatz gibt, an den ich noch nicht gedacht habe. Ich würde es vorziehen, keine temporäre Tabelle erstellen und eine Abfrage verwenden zu müssen, um festzustellen, welche Ganzzahlen fehlen.
Gibt es eine richtige Abfrage für diese Art der Suche?
(MySQL)
Antworten:
Ihre zweite Lösung mit LEFT JOIN ist bei weitem der beste Ansatz. Ich würde keine temporäre Tabelle verwenden, sondern eine reguläre Tabelle verwenden und sie jedes Mal mit neuen Werten füllen, wenn Sie die Abfrage ausführen möchten.
quelle
Es hört sich so an, als ob die "große Menge von ganzen Zahlen" immer noch erheblich kleiner ist als die Tabelle mit "Hunderttausenden von ganzen Zahlen". Mit dieser Annahme und sofern es in MySQL keine Möglichkeit gibt, ein Array Ihrer Ganzzahlen als Tabelle in Ihrer SQL-Anweisung zu verwenden, ist Ihre zweite Option wahrscheinlich die beste. Es sollte ein vollständiger Scan der temporären Tabelle und des Index für die Haupttabelle durchgeführt werden. Der Hauptvorteil besteht darin, dass nur der Index mit Hunderttausenden von Ganzzahlen einmal gescannt und dem Client nur die Ergebnisse gesendet werden müssen. Ihre Anfrage könnte (muss aber nicht) wie folgt umgeschrieben werden:
quelle
Anstelle einer temporären Tabelle und des Einfügens mit
insert into id_key_table_temp values (1),(2),(3),...,(500),(501);
können Sie eine Unterabfrage mit allen Werten erstellen, die Sie überprüfen möchten :quelle
Wie in meinem Kommentar erwähnt, ist dies wahrscheinlich besser für den Stapelüberlauf geeignet. Ich denke jedoch, dass diese beiden Lösungen nicht die besten sind:
Lösung 1 erfordert mehrere ausgewählte Anrufe, die sehr ineffizient sind
Lösung 2 ist besser, aber ich bin mir nicht sicher, ob die Kosten für das Einfügen so vieler Werte die beste Lösung sind.
Eine mögliche Lösung 3 wäre eine Abfrage:
und programmgesteuert den Unterschied zwischen Ihrer Ganzzahl und dem Inhalt der Datenbank ermitteln. Im schlimmsten Fall (da es sich um viele Ganzzahlen handelt) sollte diese Route besser sein als Lösung 1. Lösung 2 kann AUCH viele Ganzzahlen zurückgeben (wenn die Tabelle eine Reihe enthält, die nicht in Ihrem Datensatz enthalten sind) hängt davon ab ™!
quelle
Ich habe dies in StackOverflow ziemlich genau angesprochen , möchte aber näher auf die Verwendung der permanenten temporären Tabelle (PermTemp) eingehen. ( permanente Temperatur, ist das nicht ein Oxymoron? ?)
In StackOverflow hatte ich die gespeicherte Prozedur test.CreateSampleTable und test.GetMissingIntegers erstellen eine Beispieltabelle und erstellen dann eine dynamische temporäre Tabelle zum Auffüllen, bevor Sie den großen JOIN ausführen, um Unterschiede zu finden.
Dieses Mal erstellen wir die Beispieltabelle zusammen mit der permanenten Tabellentabelle.
Hier ist test.LoadSampleTables:
Nachdem Sie dies ausgeführt haben, sind hier die Tabellen und deren Inhalt:
Hier sind die Trigger für die PermTemp-Tabelle
Jetzt können Sie einen neuen Datensatzstapel importieren, Tabelle test.weekly_batch, einige zuvor verwendete Schlüssel, andere brandneue Schlüssel:
Nehmen wir test.weekly_batch und führen es sicher in test.id_key_table_keys ein und bilden die Tabelle test.new_keys_to_load:
Hier ist das Ergebnis:
Verwenden Sie ab diesem Zeitpunkt einfach die Tabelle new_keys_to_load als Liste der brandneuen Schlüssel, die importiert werden sollen. Da new_keys_to_load kleiner als die PermTemp-Tabelle ist, sollten Sie immer new_keys_to_load auf der linken Seite von LEFT JOIN verwenden.
quelle