2012-11-05 12 views
5

Ich habe zwei TabellenParse in MySQL mit Komma als Trennzeichen

Table1 mit Liste der Benutzer durch Komma getrennt

Name UserID 
abc  A,B,C,D 
def  A,B,C 

Table2

Name UserID 
abc A 
abc B 
abc C 
def A 
def B 

Ich brauche die Benutzer zu finden, die in Tabelle 1 sind für jeden Namen, aber nicht in Tabelle2 (Es wird niemals eine Instanz geben, wenn ein Paar "Benutzer-ID zu Name" in Tabelle 2 vorhanden ist, aber nicht in Tabelle1 als CSV).

sollte die Ausgabe

Name UserID 
abc  D 
def  C 

sein, die ich mit PHP dies tun können, aber ist es eine Möglichkeit, dies durch eine Abfrage durchgeführt werden kann? Ich bin mir nicht sicher, wo ich anfangen soll, falls ich das als Anfrage mache. Kann ich MySQL mit Komma als Trennzeichen analysieren?

+0

'Ich muss die Benutzer finden, die in Tabelle1 für ** jeder Name **, aber nicht in Tabelle2' sind. Aber 'D' in Tabelle1 ist nicht in ** jeder Name **. 'D' ist nur in' abc'. Wie kommt es dann in Ihre gewünschte Ausgabe? – hims056

+0

Was ich meine, ist jeder Name UserID Paar .. – Ank

+3

Sie haben denormalisierte Daten in Ihrer Datenbank. Ich würde Ihnen empfehlen, ein PHP-Skript auszuführen, um die Daten zu normalisieren und die Ergebnisse in der normalisierten Datenbank in Ihrer Datenbank zu speichern. Auf diese Weise wird diese bestimmte Abfrage und alle zukünftigen Abfragen viel einfacher. Im Allgemeinen ist es gut, durch Kommas getrennte Werte zu vermeiden, die in Datenbankfeldern gespeichert sind. Weitere Informationen zur Datenbanknormalisierung finden Sie hier: http://databases.about.com/od/specificproducts/a/normalization.htm –

Antwort

3

Ich steckte Ihre Testdaten in ein Testschema in SQLFiddle und führte die folgende Abfrage aus.

Hier ist der Link zu SQLFiddle mit dem Test und positive Ergebnisse: http://sqlfiddle.com/#!2/83dfd/4/0

Hier ist die Abfrage:

SELECT 
COALESCE(NORMALIZED_TABLE1.NAME, TABLE2.NAME) AS NAME, 
COALESCE(NORMALIZED_TABLE1.USERID, TABLE2.USERID) AS USERID 
FROM (
    SELECT NAME, 
    SUBSTRING(
      USERID 
      FROM CASE 
       WHEN INDEX_TABLE.POS = 1 THEN 1 
       ELSE INDEX_TABLE.POS + 1 
       END 
      FOR CASE LOCATE(',', USERID, INDEX_TABLE.POS + 1) 
       WHEN 0 THEN CHARACTER_LENGTH(USERID) + 1 
       ELSE LOCATE(',', USERID, INDEX_TABLE.POS + 1) 
       END 
       - CASE 
       WHEN INDEX_TABLE.POS = 1 THEN 1 
       ELSE INDEX_TABLE.POS + 1 
       END 
    ) AS USERID 
    FROM TABLE1 
    INNER JOIN (
      SELECT @rownum:[email protected]+1 POS 
      FROM (
      SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 
      UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 
      UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 
     ) a, (
      SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 
      UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 
      UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 
     ) b, (
      SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 
      UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 
      UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 
     ) c, (SELECT @rownum:=0) r 
    ) INDEX_TABLE 
    ON INDEX_TABLE.POS <= CHAR_LENGTH(TABLE1.USERID) 
    AND (
      INDEX_TABLE.POS = 1 
      OR SUBSTRING(USERID FROM INDEX_TABLE.POS FOR 1) = ',' 
    ) 
) AS NORMALIZED_TABLE1 
LEFT OUTER JOIN TABLE2 
ON NORMALIZED_TABLE1.NAME = TABLE2.NAME 
AND NORMALIZED_TABLE1.USERID = TABLE2.USERID 
WHERE TABLE2.NAME IS NULL; 

Wenn Sie sehr lange Spaltenbreite in Tabelle 1 haben Sie möglicherweise die „INDEX_TABLE erweitern müssen "Unterabfrage. Sie können kopieren und einfügen mit dem Code über diesen Link zu tun:
http://www.experts-exchange.com/Database/MySQL/A_3573-A-MySQL-Tidbit-Quick-Numbers-Table-Generation.html

+1

Ein vollständiger äußerer Join prüft auf fehlende Daten aus beiden Tabellen. Ich habe gerade gemerkt, dass nur Daten von ihnen fehlen können. Die gleiche Abfragelogik würde immer noch funktionieren, aber Sie könnten im obigen Code den vollständigen äußeren Join durch einen rechten äußeren Join ersetzen. –

+0

ODER ... Sie könnten die 'Join'-Syntax und die aktuelle where-Klausel durch' where not exists (...) Klausel.Das wäre wahrscheinlich der eleganteste Weg, vielleicht auch etwas schneller. –

+0

Da Sie erkannt haben, dass Sie die Ergebnisse aus beiden Tabellen nicht verpassen möchten, ist es auch passiert, dass dies viel einfacher wäre und genauso gut funktioniert. SELECT NAME, USERID VON TABLE2 WO NICHT VORHANDEN ( SELECT 0 FROM TABLE1 WHERE TABLE1.NAME = TABLE2.NAME AND ( '%' TABLE1.USERID LIKE + TABLE2.USERID + '%' ODER TABLE1.USERID WIE TABLE2.USERID + ',%' ODER TABLE1.USERID WIE "%", + TABLE2.USERID ) ); –

0

Wenn Sie eine Tabelle festgelegt haben (Sie möchten an diesen Tabellen arbeiten), entwerfen Sie eine Klasse, um Daten von ihnen zu lesen, anstatt die festgelegten Daten direkt aus diesen vordefinierten Tabellen zu speichern. Lassen Sie Ihr Objekt die gelesenen Daten live in Ihrer Anwendungsdomäne verarbeiten, um eine vollständige Zugänglichkeit zu erhalten. :-D

+0

Danke für Ihre Antwort. Ich kann sehr gut ein PHP-Skript schreiben, um die Benutzerspalte zu analysieren. Ich habe jedoch ein JavaScript/PHP-Modul erstellt, das eine SQL-Abfrage als Eingabe akzeptiert und die Ergebnisse in einem geordneten Format anzeigt. Ich habe mich gefragt, ob es eine Abfrage für dieses Problem geben kann, die ich in mein Modul passen und direkt die Ausgabe bekommen kann. Ich hoffe es macht Sinn !! – Ank

+0

:-D auch zu achtsam. –

Verwandte Themen