2016-04-30 8 views
1

Ich habe zwei Tabellen.Wie Regexp auf die Ergebnisse einer Unterabfrage verwenden?

Benutzer die


IDPHONE_NO ID und Telefonnummer hat

1 ---- 9912678

2 ---- 9.912.323

3 ---- 9912366


Admission-Tabelle, die IDTelefonnummer

IDPHONE_NO

6 --- 991267823

hat 7 --- 991236621

8 --- 435443455

9 --- 243344333

Ich möchte alle Telefonnummer von Eintritt des Tabelle zu finden, die gleichen Muster wie Benutzer Tisch und Update hat es in der Benutzertabelle.

So versuche ich diese

select phone_no from admission where phone_no REGEXP (SELECT phone_no 
FROM `users` AS user 
WHERE user.phone_no REGEXP '^(99)+[0-9]{8}') 

Aber ich erhalte diesen Fehler Subquery mehr als 1 Zeile zurückgibt

nach Hilfe suchen.

+1

Was meinst du genau, von "hat das gleiche Muster"? Raten Sie von Ihren Beispielen, ist es tatsächlich "beginnt mit"? – Bohemian

+0

Die Tabelle für den Benutzer und die Tabelle für den Zugang haben beide die gleichen Telefonnummern, die mit 99 beginnen, aber die Tabelle des Benutzers fehlt nach 2 Ziffern. Zuerst möchte ich alle diese Nummern aus der Tabelle '^ [99] + [0-9] {8}' filtern und dann die Telefonnummer 9912678 des Benutzers mit der Telefonnummer 991267823 der Telefonnummer – shuvrow

+0

übereinstimmen, wenn ich Daten für die so formatierte Tabelle des Benutzers abfrage '9912678 | 9912323 | 9912366' die Abfrage wird ausgeführt, aber ich weiß nicht, wie ich das machen soll. Danke – shuvrow

Antwort

1

eine dieser Abfragen Versuchen:

SELECT a.phone_no 
FROM admission a 
JOIN users u on a.phone_no LIKE concat(u.phone_no, '__') 
WHERE u.phone_no REGEXP '^(99)+[0-9]+$' 

oder

SELECT a.phone_no 
FROM admission a 
JOIN users u on a.phone_no REGEXP concat('^', u.phone_no, '[0-9]{2}$') 
WHERE u.phone_no REGEXP '^(99)+[0-9]+$' 

Wenn die Anzahl der "nachlauf Ziffern" nicht festgelegt ist, können Sie auch:

LIKE concat(u.phone_no, '%') 

oder

REGEXP concat('^', u.phone_no, '[0-9]*$') 

In diesem Fall müssen Sie jedoch möglicherweise SELECT DISTICT a.phone_no verwenden, wenn es möglich ist, dass eine eine Untersequenz einer anderen ist (z. 99123 und 991234).

aktualisieren

Nach ein paar Tests mit 10K Zeilen für Benutzer-Tabelle ausgeführt und 100K Zeilen für die Zulassung Tabelle i auf die folgende Abfrage kam:

SELECT a.phone_no 
FROM admission a 
JOIN users u 
    ON a.phone_no >= u.phone_no 
    AND a.phone_no < CONCAT(u.phone_no, 'z') 
    AND a.phone_no LIKE CONCAT(u.phone_no, '%') 
    AND a.phone_no REGEXP CONCAT('^', u.phone_no, '[0-9]*$') 
WHERE u.phone_no LIKE '99%' 
    AND u.phone_no REGEXP '^(99)+[0-9]*$' 
UNION SELECT 0 FROM (SELECT 0) dummy WHERE 0 

fiddle

Auf diese Weise können Sie Verwenden Sie REGEXP und immer noch eine großartige Leistung. Diese Abfrage wird in meinem Testfall fast sofort ausgeführt.

Logischerweise brauchen Sie nur die Bedingungen REGEXP. Bei größeren Tabellen könnte die Abfrage jedoch eine Zeitüberschreitung aufweisen. Wenn Sie eine LIKE-Bedingung verwenden, wird die Ergebnismenge vor der REGEXP-Prüfung gefiltert. Aber selbst mit LIKE funktioniert die Abfrage nicht sehr gut. Aus irgendeinem Grund verwendet MySQL keine Bereichsüberprüfung für den Join. So fügte ich eine explizite Bereichsprüfung:

ON a.phone_no >= u.phone_no 
    AND a.phone_no < CONCAT(u.phone_no, 'z') 

Damit können Sie überprüfen die LIKE-Bedingung von dem Teil JOIN entfernen.

Der UNION-Teil ist ein Ersatz für DISTICT. MySQL scheint DISTINCT in eine GROUP BY-Anweisung zu übersetzen, die nicht gut funktioniert. Wenn ich UNION mit einer leeren Ergebnismenge verwende, zwinge ich MySQL, Duplikate nach dem SELECT zu entfernen. Sie können diese Zeile entfernen, wenn Sie eine feste Anzahl nachkommender Ziffern verwenden.

Sie können die REGEXP Muster an Ihre Bedürfnisse anpassen:

... 
    AND a.phone_no REGEXP CONCAT('^', u.phone_no, '[0-9]{2}$') 
... 
    AND u.phone_no REGEXP '^(99)+[0-9]{8}$' 
... 

Wenn Sie nur REGEXP brauchen die Länge des PHONE_NO zu überprüfen, können Sie auch eine LIKE-Bedingung mit dem ‚_‘ Platzhalter verwenden können.

AND a.phone_no LIKE CONCAT(u.phone_no, '__') 
... 
    AND u.phone_no LIKE '99________$' 

oder kombinieren Sie eine LIKE-Bedingung mit einer STR_LENGTH-Prüfung.

+0

Join mit 'LIKE' ohne Verwendung von' DISTINCT' wird Duplikate zurückgeben, besser 'EXISTS' anstatt der Tabelle beizutreten. – maraca

+0

Danke @maraca. "DISTINCT" wird jedoch nur benötigt, wenn die Anzahl der "abschließenden Ziffern" nicht festgelegt ist. –

+0

@PaulSpiegel Ihre erste Abfrage gibt ein leeres Ergebnis zurück, die zweite Abfrage gibt mehr Werte zurück, als die Eingabetabelle, und die dritte Abfrage funktioniert einwandfrei. Danke – shuvrow

1

Ich denke, das tut, was Sie wollen, ich einige Verbesserungen tat (SQLfiddle):

select * from admission a where exists (
    select * from (
    select substr(phone_no, 1, 7) pn from users where phone_no REGEXP '^99[0-9]{5}' 
) o where a.phone_no like concat(o.pn, '%') 
) 

ich die Regex ändern hatte keine Spiele zu bekommen. Wenn die Länge fest ist, kann die zweite Prüfung einfach mit like durchgeführt werden. Wir schauen in die user Tabelle, um zu sehen, ob dort exists irgendeine phone_no, die die Kriterien für die Zulassungsnummer, die wir derzeit betrachten, entspricht.

+0

Danke Seine Arbeit :) – shuvrow

1

Regex egal. Sie verbinden eine einfache like

select distinct a.phone_no 
from user u 
join admission a on a.phone_no like concat(u.phone_no, '%') 
where u.phone_no like '99%' 

Das distinct Schlüsselwort wird nur dann benötigt, wenn es entweder doppelte Zahlen in der Tabelle admission sind, und/oder in der user Tabelle. Andernfalls kann es weggelassen werden.

+0

Sorry, aber wie die Abfrage ist falsch und hat genau das Problem, über das er sich beschwert: die Telefonnummern werden multipliziert (es sei denn, Sie tun eine deutliche). – maraca

+0

@maraca Sie sind falsch. Der Fehler OP hat nichts damit zu tun, doppelte Zeilen aus dem Ergebnis zurückzugeben; Dies liegt daran, dass die * Unterabfrage * von OP mehrere Zeilen zurückgibt, wenn sie als einwertige Ergebnisse in der Abfrage verwendet werden. Die Verwendung von "distinct" in der Abfrage von OP würde OPs Fehler nicht verschwinden lassen. Die Verwendung von "distinct" in meiner Abfrage wäre nur erforderlich, wenn Duplikate in den Rohdaten vorhanden wären (Ich habe meine Antwort aktualisiert, um dies zu erklären). – Bohemian

+0

@maraca wieder, ich stimme nicht mit allem überein, was Sie gesagt haben. Um klar zu sein, wenn zwei Zulassungsnummern beide mit der gleichen Benutzernummer übereinstimmen (dh beginnen), werden beide in der Ausgabe gemäß den Anforderungen des OP erwartet. Wie ich bereits sagte, kann eine Duplizierung in der Ausgabe nur auftreten, wenn in einer der Tabellen tatsächliche Duplikate vorhanden sind. Außerdem ist 'like' durchaus angemessen, da die Semantik" beginnt mit "ist, was am einfachsten, am besten und am klarsten als" like "Präfix% 'ausgedrückt wird. Die Verwendung von "exists" wird sehr schlecht funktionieren, da die Unterabfrage für jede Zeile einmal ausgeführt werden muss, wobei "Gefällt mir" nur einen Durchlauf verwendet. – Bohemian