Es heißt Entity-Attribute-Value (manchmal auch "Name-Wert-Paare") und ist ein klassischer Fall von "einem runden Stift in einem quadratischen Loch", wenn Menschen das EAV-Muster in einer relationalen Datenbank verwenden.
Hier ist eine Liste, warum Sie EAV nicht verwenden sollten :
- Sie können keine Datentypen verwenden. Es spielt keine Rolle, ob der Wert ein Datum, eine Zahl oder ein Geld (dezimal) ist. Es wird immer zu Varchar gezwungen werden. Dies kann alles Mögliche sein, von einem kleinen Leistungsproblem bis hin zu einem massiven Bauchweh (mussten Sie jemals eine 1-Cent-Variante in einem monatlichen Roll-up-Bericht runterjagen?).
- Sie können Einschränkungen nicht (leicht) erzwingen. Es erfordert eine lächerliche Menge an Code, um "Jeder muss eine Höhe zwischen 0 und 3 Metern haben" oder "Alter darf nicht null und> = 0 sein" zu erzwingen, im Gegensatz zu den 1-2 Zeilen, die jede dieser Einschränkungen sein würde in einem richtig modellierten System.
- In Bezug auf das oben Gesagte können Sie nicht ohne Weiteres garantieren, dass Sie die Informationen erhalten, die Sie für jeden Kunden benötigen (bei einem fehlt möglicherweise das Alter, bei dem nächsten fehlt möglicherweise die Größe usw.). Du kannst es schaffen, aber es ist verdammt viel schwieriger als
SELECT height, weight, age FROM Client where height is null or weight is null
.
- Erneut ist es viel schwieriger, doppelte Daten zu erkennen (was passiert, wenn Sie für einen Client zwei Altersstufen angeben? Wenn Sie die Daten wie unten angegeben deaktivieren, erhalten Sie zwei Ergebniszeilen, wenn Sie ein doppeltes Attribut haben. Wenn ein Client verwendet wird hat zwei separate Einträge für zwei Attribute, Sie erhalten vier Zeilen aus der Abfrage unten).
- Sie können nicht einmal garantieren, dass die Attributnamen konsistent sind. "Age_yr" kann "AGE_IN_YEARS" oder "age" werden. (Zugegeben, dies ist weniger problematisch, wenn Sie einen Auszug erhalten, als wenn Leute Daten einfügen, aber dennoch.)
- Jede Art von nicht trivialer Abfrage ist eine völlige Katastrophe. Um ein EAV-System mit drei Attributen zu relationalisieren, sodass Sie es auf rationale Weise abfragen können, sind drei Joins der EAV-Tabelle erforderlich.
Vergleichen Sie:
SELECT cID.ID AS [ID], cH.Value AS [Height], cW.Value AS [Weight], cA.Value AS [Age]
FROM (SELECT DISTINCT ID FROM Client) cID
LEFT OUTER JOIN
Client cW ON cID.ID = cW.ID AND cW.Metric = "Wt_kg"
LEFT OUTER JOIN
Client cH ON cID.ID = cH.ID AND cW.Metric = "Ht_cm"
LEFT OUTER JOIN
Client cA ON cID.ID = cA.ID AND cW.Metric = "Age_yr"
Zu:
SELECT c.ID, c.Ht_cm, c.Wt_kg, c.Age_yr
FROM Client c
Hier ist eine (sehr kurze) Liste, wann Sie EAV verwenden sollten:
- Wenn es gibt absolut keinen Weg drum herum und Sie haben Schema-weniger Daten in Ihrer Datenbank zu unterstützen.
- Wenn Sie nur "Zeug" speichern müssen und nicht erwarten, dass es in einer strukturierteren Form benötigt wird. Vorsicht, das Monster nennt sich "wechselnde Anforderungen".
Ich weiß, dass ich diesen ganzen Beitrag damit verbracht habe, zu erklären, warum EAV in den meisten Fällen eine schreckliche Idee ist - aber es gibt einige Fälle, in denen es notwendig / unvermeidbar ist. In den meisten Fällen (einschließlich des obigen Beispiels) ist dies jedoch weitaus mühsamer als es sich lohnt. Wenn Sie eine breite Unterstützung für die Dateneingabe vom Typ EAV benötigen, sollten Sie die Speicherung in einem Schlüsselwertsystem in Betracht ziehen, z. B. Hadoop / HBase, CouchDB, MongoDB, Cassandra, BerkeleyDB.
Entitätsattributwert (EAV)
Es wird von vielen als Anti-Muster angesehen, auch von mir.
Hier sind Ihre Alternativen:
Verwenden Sie die Vererbung von Datenbanktabellen
Verwenden Sie XML-Daten und SQLXML-Funktionen
Verwenden Sie eine NOSQL-Datenbank wie HBase
quelle
In PostgreSQL ist ein sehr guter Weg, mit EAV-Strukturen umzugehen, das Zusatzmodul
hstore
, das für Version 8.4 oder höher verfügbar ist. Ich zitiere das Handbuch:Seit Postgres 9.2 gibt es auch den
json
Typ und eine Vielzahl von Funktionen, die dazugehören (die meisten wurden mit 9.3 hinzugefügt ).Postgres 9.4 fügt
jsonb
der Liste der Optionen den (größtenteils überlegenen!) "Binären JSON" -Datentyp hinzu . Mit erweiterten Indexoptionen.quelle
Wenn Sie über eine Datenbank verfügen, die die EAV-Struktur verwendet, können Sie die Daten auf verschiedene Arten abfragen.
Die Antwort von @ Simon zeigt bereits, wie eine Abfrage mit mehreren Joins ausgeführt wird.
Verwendete Beispieldaten:
Wenn Sie ein RDBMS mit einer
PIVOT
Funktion verwenden ( SQL Server 2005+ / Oracle 11g + ), können Sie die Daten folgendermaßen abfragen:Siehe SQL Fiddle with Demo
Wenn Sie keinen Zugriff auf eine
PIVOT
Funktion haben, können Sie eine Aggregatfunktion mit einerCASE
Anweisung verwenden, um die Daten zurückzugeben:Siehe SQL Fiddle with Demo
Diese beiden Abfragen geben Daten im Ergebnis zurück:
quelle
Es ist lustig zu sehen, wie das EAV-Datenbankmodell von einigen kritisiert und sogar als "Anti-Pattern" angesehen wird.
Für mich sind die Hauptnachteile :
Sie sollten diese Lösung jedoch auf keinen Fall verwerfen. Deshalb:
quelle