[MySQL] - Dynamische Attribute erstellen und durchsuchen

Mindwinder

Mitglied
Hi liebe Leute,
ich benötige mal einen Denkanstoß für folgendes Problem:
4 Tabellen:
user -> id, passwort,...
freunde -> id, user_id, adresse, name, standart, attribute, ...

Die Tabelle freunde soll per user um unterschiedliche Attribute erweitert werden, hierzu die 2 Tabellen:

attribute -> id, user_id, AttributName
werte_der_attribute -> id,freunde_id,attribut_id, wert

Eintragen und Auslesen stellt soweit kein Problem dar - allerdings komme ich nicht drauf wie ich eine Suche realisieren kann, die mehrere der zusätzlichen Attribute mit AND verknüpft.
Erster Ansatz war ein Join von freunde auf werte_der_attribute
und dann eine WHERE clause mit attribut_id=x AND value=Y - klappt solange ich nur nach einem bestimmen Wert Suche. Ein OR würde auch funktionieren über attribut_id=x AND value=Y OR attribut_id=s AND value=t. Bin schon am überlegen, ob ich die OR Verknüpfung benutze, dann die Ergebnisse pro freunde_id zähle und diese gegen die Anzahl der übergebenen Suchparameter abgleiche, aber irgendwie muss das doch einfacher gehen.

Hoffe mal das meine Beschreibung einigermaßen verständlich ist und irgendwer eine Lösung parat hat.

Andere Realisierungen finde ich irgendwie nicht so elegant, können wir aber gerne diskutieren.
1. freunde um ein Feld erweitern und dort die Werte abspeichern in etwa in der Form attribut_id="wert"; und eine Suche dann über reguläre Ausdrücke
Nachteil: Performance
2. freunde oder werte der attribiute um x Felder erweitern und in der Tabelle attribute max. x Felder zulassen
Nachteil: die Anzahl der Attribute ist beschränkt und es gibt Unmengen an Leereinträgen
3. Eine Temporäre Tabelle erzeugen

Nette Grüße,

Mindwinder
 
Mir kommt spontan auch nur gerade die Idee mit OR und COUNT()
SQL:
SELECT
	user_id,
	freunde_id
FROM
	attribute AS a
	LEFT JOIN werte_der_attribute AS w
		ON a.id = w.attribut_id
WHERE
	a.user_id = 1
	AND (
		a.AttributName = 'u1_a1' AND w.wert LIKE '%a1'
		OR a.AttributName = 'u1_a2' AND w.wert LIKE '%a2'	
	)
GROUP BY
	user_id,
	freunde_id
HAVING
	COUNT(DISTINCT w.id) = 2;
 
Zuletzt bearbeitet von einem Moderator:
Hi Yaslaw,
danke für die schnelle Antwort - zur Verifizierung, ob dieses tatsächlich die sinnvollste Lösung ist würde ich gerne ein Schritt zurück machen und das ganze vereinfachen.
Nehmen wir eine n:m Beziehung derart an: person - person_verteiler - verteiler an. Gehe ich tatsächlich über count um festzustellen, ob eine person Mitglied in x bestimmten Verteilern ist - bzw wenn ich die Personen suche die Mitglied in x bestimmten Verteilern sind. Denkbar wäre ja auch so etwas

PHP:
SELECT * FROM  personen
WHERE 
id IN (
SELECT person_id as id FROM personen_verteiler WHERE verteiler_id=x
)
AND
id IN (
SELECT person_id as id FROM personen_verteiler WHERE verteiler_id=y
) ...

oder die einzelnen SELECTS ineinander verschachteln
 
Nun, so eleganter ists nicht wirklich

SQL:
SELECT DISTINCT
	user_id,
	freunde_id
FROM
	attribute AS a
	LEFT JOIN werte_der_attribute AS w
		ON a.id = w.attribut_id
WHERE
	(a.user_id, w.freunde_id) IN  (
		SELECT
			a1.user_id,
			w1.freunde_id
		FROM
			attribute AS a1
			INNER JOIN werte_der_attribute AS w1
				ON a1.id = w1.attribut_id
		WHERE
			a1.AttributName = 'u1_a1' AND w1.wert LIKE '%a1'
	) AND 
	(a.user_id, w.freunde_id) IN  (
		SELECT
			a1.user_id,
			w1.freunde_id
		FROM
			attribute AS a1
			INNER JOIN werte_der_attribute AS w1
				ON a1.id = w1.attribut_id
		WHERE
			a1.AttributName = 'u1_a2' AND w1.wert LIKE '%a2'
	);

Wenn du natürlich die Verbindung als View speicherst, wirds eleganter
SQL:
CREATE VIEW vw_user_attributes AS 
SELECT  
	w.attribut_id,  
	a.user_id,  
	w.freunde_id,  
	a.AttributName,  
	w.wert
FROM
	attribute AS a  
	INNER JOIN werte_der_attribute AS w
		ON a.id = w.attribut_id ;
Und dann die Lösung
SQL:
SELECT DISTINCT
	user_id,
	freunde_id
FROM
	vw_user_attributes
WHERE
	(user_id, freunde_id) IN  (
		SELECT
			user_id,
			freunde_id
		FROM
			vw_user_attributes
		WHERE
			AttributName = 'u1_a1' AND wert LIKE '%a1'
	) AND 
	(user_id, freunde_id) IN  (
		SELECT
			user_id,
			freunde_id
		FROM
			vw_user_attributes
		WHERE
			AttributName = 'u1_a2' AND wert LIKE '%a2'
	);
 
Zuletzt bearbeitet von einem Moderator:

Neue Beiträge

Zurück