2016-05-24 5 views
0

Ich möchte eine MySQL-Abfrage erstellen, um die längste Übereinstimmung (einer gegebenen IP-Adresse im Quad-Punkt-Format) zu finden, die in einer Tabelle von Subnetzen vorhanden ist.MySQL LEAST() mit beliebiger Anzahl von Parametern; längste Übereinstimmung in einer Tabelle

Schließlich würde ich gerne eine LEFT JOIN erstellen, die jede Quad-gepunktete IP-Adresse in einer Tabelle zusammen mit ihren längsten Übereinstimmungen in einer anderen Tabelle angezeigt wird. Ich möchte keine temporären Tabellen erstellen oder sie als verschachtelte Abfrage strukturieren.

Ich bin ein wenig von einem MySQL-Neuling, aber was ich denke ist so etwas wie dieses:

SELECT `ip_address` 
    LEFT JOIN ON 
    SELECT `subnet_id` 
    FROM `subnets_table` 
    WHERE (`maximum_ip_value` - `minimum_ip_value`) = 
    LEAST(<list of subnet intervals>) 
     WHERE INET_ATON(<given ip address>) > `minimum_ip_value` 
     AND INET_ATON(<given ip address>) < `maximum_ip_value`; 

Derart, dass minimum_ip_value und maximum_ip_value sind die niedrigsten und höchsten Dezimal-Format ip möglichen Adressen in einem bestimmten subnet-- zB für das Subnetz 172.16.0.0/16:

minimum_ip_value = 2886729728 (or 172.16.0.0) 
maximum_ip_value = 2886795263 (or 172.16.255.255) 

und <list of subnet intervals> enthält alle Intervalle in subnets_table wo <given ip address> zwischen minimum_ip_value und 012.

Und wenn mehr als ein Intervall <given ip address> enthält, dann wird das kleinste Intervall (d. H. Das kleinste Subnetz oder die spezifischste und "längste" Übereinstimmung) verbunden.

Letztendlich will ich nur den subnet_id Wert, der diesem Intervall entspricht.

Also meine Fragen sind:

1) Kann ich die am wenigsten() Funktion mit einer beliebigen Anzahl von Parametern verwenden? Ich würde gerne jede Zeile von subnets_table oder genauer gesagt das Intervall jeder Zeile zwischen minimum_ip_value und maximum_ip_value vergleichen und das kleinste Intervall auswählen.

2) Kann ich alle diese Berechnungen innerhalb einer LEFT JOIN Abfrage durchführen? Mir geht es gut mit Vorschlägen, die schnell und gekapselt sind und wiederholte Abfragen der gleichen Daten vermeiden.

Ich frage mich, ob dies sogar in einer einzigen Abfrage durchgeführt werden kann (d. H. Ohne Abfrage der Subnets-Tabelle für jede IP-Adresse), aber ich weiß nicht genug, um es auszuschließen. Bitte sagen Sie mir, wenn es so aussieht, als ob es nicht funktioniert, also kann ich einen anderen Winkel versuchen.

Danke.

+0

Bitte beschränken Sie Ihre Tags auf das von Ihnen verwendete RDBMS. MySQL und SQL Server erfordern oft unterschiedliche Lösungen für das gleiche Problem. –

Antwort

0

Nach einigen Recherchen und Test & Fehlern, ich sehe, dass es ein paar Probleme mit der Prototyp-Abfrage ist oben:

Die LEAST() Funktion nur eine festgelegte Anzahl von Argumenten entgegennimmt. Gemäß meiner ursprünglichen Frage möchte ich eine Funktion, die mit einer beliebigen Anzahl von Argumenten oder jeder Zeile in einer Tabelle arbeitet. Das ist eine andere Funktion in MySQL, MIN().

Die Funktion MIN() hat eine niedrigere Priorität als die JOIN Funktionen in MySQL und wird nach den JOIN Funktionen in einer beliebigen Abfrage ausgewertet. Daher kann ich JOIN über die MIN() einer Reihe von Werten nicht, weil die MIN() noch nicht zur Zeit der JOIN durchgeführt wird.

Die einzige Möglichkeit, dieses Problem zu lösen, war zwei separate Abfragen auszuführen: eine mit der MIN(), die zuerst ausgeführt wurde, und eine weitere mit der JOIN, durchgeführt mit den Ergebnissen der ersten Abfrage. Dies bedeutete, dass für eine Tabelle mit n Reihen, würde ich n^n Abfragen durchführen, statt n Abfragen. Das war nicht akzeptabel.

Um das Problem zu umgehen, schrieb ich ein neues Skript, das die Datenbank ändert, bevor eine dieser Abfragen überhaupt ausgeführt wird. Jedes Subnetz erhält einen eigenen "Bucket" mit IP-Werten, und alle Werte in diesem Bereich werden diesem Subnetz zugeordnet. Wenn ein spezifischeres (d. H. Kleineres) Subnetz ein weniger spezifisches (d. H. Größeres) Subnetz überlappt, wird der spezifischere Bereich nur auf das kleinere Subnetz abgebildet und das größere Subnetz behält nur die Werte aus dem weniger spezifischen Bereich bei. Jetzt fällt jede gegebene IP-Adresse in nur einen "Bucket" und wird nur einem Subnetz zugeordnet, was die spezifischste Übereinstimmung ist. Ich kann JOIN auf diesem Spiel und muss nie um die MIN() Funktion kümmern.