2017-12-16 8 views
-2

Ich habe Tabellen wie unten;Gibt es eine Open-Source-Lösung oder einen schnellen Start, um mit dem Tag-basierten Record-Systerm zu beginnen, außer meinem bestehenden 4-Tabellen-System, das ich verwende?

Ich habe 4 MySQL-Tabellen wie folgt;

Tabelle1

======================== 
id1 | brand | tags 
======================== 
111 | mercedes | xx 
-----+-----------+------ 
222 | mercedes | yy 
-----+-----------+------ 
333 | ford  | xx,yy 
-----+-----------+------ 
444 | audi  | yy,zz 
-----+-----------+------ 
555 | jaguar | xx,yy,zz 
======================== 

Table2

======================== 
id2 | model | id1 
======================== 
aaa | s class | 111 
-----+-----------+------ 
bbb | figo  | 333 
-----+-----------+------ 
ccc | a6  | 444 
-----+-----------+------ 
ddd | xf  | 555 
-----+-----------+------ 
eee | a4  | 444 
======================== 

Table3

============ 
id1 | id3 
============ 
111 | xx 
-----+------ 
222 | yy 
-----+------ 
333 | xx 
-----+------ 
333 | yy 
-----+------ 
444 | yy 
-----+------ 
444 | zz 
-----+------ 
555 | xx 
-----+------ 
555 | yy 
-----+------ 
555 | zz 
============ 

Table4

================== 
id3 | tagdetails 
================== 
xx | description 
-----+------------ 
yy | description 
-----+------------ 
zz | description 
================== 

Meine Absicht ist es Kombination suchen. Ich benutze PHP + MySQL. Ich hole Datensätze mit Tags, die ich als Eingabe gebe. Zum Beispiel, wenn ich xx gebe, bekomme ich mercedes, ford und jaguar. Wenn ich xx,yy,zz gebe, bekomme ich jaguar alleine. Dies ist eine sehr ineffiziente Lösung, wenn eine große Anzahl von Datensätzen vorhanden ist. Gibt es eine frei verfügbare ähnliche Lösung?

Vielen Dank.

+0

Ja, Sie sollten die Autonamen als CSV-Daten nicht speichern, sondern brechen sie in separate Datensätze aus. Aber haben Sie eine andere Frage, oder wenn nicht, warum haben Sie dann diese anderen Tabellen veröffentlicht? –

+0

Ich habe die gesamten Tabellen gepostet, um zu zeigen, dass ich diese Frage nicht posten werde, um SO als mein PRA zu verwenden. Ich verwende derzeit diese Lösung, und wie Sie sagten, verstehe ich, dass dies nicht effizient ist.Ich frage, ob es eine effiziente Lösung gibt, die verfügbar ist, so dass ich sie gemäß meinen Anforderungen anpassen kann, wie "Apache Ignite" für das Caching. –

+0

Fragen Sie nach Möglichkeiten, Dinge zu beschleunigen, ohne Ihr Schema zu ändern, oder suchen Sie nach Möglichkeiten, Ihr Design zu verbessern? –

Antwort

0

Sie können eine Spalte SET für diese Art von Anwendung verwenden. Wenn Sie die Spalte erstellen, geben Sie eine Liste mit bis zu 64 möglichen Werten an, die die Spalte enthalten kann. In der Datenbank werden diese jedoch als binäre Bitmenge gespeichert. Das erste Element ist also 1, das zweite 2, das dritte 4, 8, 16 , 32 usw.

Sie können auf sie mit Namen oder numerisch zugreifen und suchen mit LIKE gegen die Textwerte oder alle Bit-Operatoren verwenden. Das Schöne an einem Bit Set ist, dass jede mögliche Kombination von Tags eine eindeutige Nummer hat. Wenn xxx = 1 und yyy = 2 dann ein Auto mit beiden wird Tags = 3.

Angenommen, Ihre Tabellenstruktur geschrieben hier genau ist dann die folgenden wird die erforderlichen Spalten hinzufügen und die Werte für alles berechnen:

SELECT @tags:= GROUP_CONCAT(id3 SEPARATOR '", "') FROM table4; 
SET @s = CONCAT('ALTER TABLE table1 ADD tagset SET("', @tags, '")'); 
PREPARE stmt FROM @s; 
EXECUTE stmt; 
DEALLOCATE PREPARE stmt; 
ALTER TABLE table4 ADD tags int NULL; 
SET @tags:= NULL; 
UPDATE table4 SET tags = (SELECT (@tags:= IF(@tags IS NULL, '1', @tags * 2))); 
UPDATE table1 SET tagset = tags; 

Diese eine Spalte ergänzt mit den numerischen Werten für jeden Tag table4 und einem SET Spalte zu Tabelle1 mit den richtigen Tags gesetzt. Sie strukturieren dann Ihre Abfragen, um die korrekten Werte basierend auf dem Tag-Namen zu berechnen.

SELECT * FROM table1 WHERE tagset = (SELECT SUM(tags) FROM table4 WHERE id3 IN ('xx', 'yy')); 
// Using '=' will only return matches with tag xx and yy exactly 

SELECT * FROM table1 WHERE tagset & (SELECT SUM(tags) FROM table4 WHERE id3 IN ('xx')); 
// Using '&' will return all matches with xx 

Alle anderen Bitvergleichsoperatoren können verwendet werden. Mehr Infos here und here

Es gibt eine Demo sqlfiddle here

Verwandte Themen