SQL Statement oder Alternative gesucht

SaxnPaule

Fleet Admiral
Registriert
Okt. 2010
Beiträge
10.145
Hallo Community,

ich bastel gerade an einem kleinem Programm (JAVA) und bin auf ein Problem gestoßen bei dem ich nicht weiterkomme.

Es gibt eine Hand voll nutzerdefinierter Werte. Im jetzigen Beispiel A, B, E, G, I und K
Insgesamt kann es eine beliebige Anzahl aus ca. 100 möglichen Werten sein.

Des Weiteren habe ich ca. 10.000 Datensätze, welche eine beliebige Anzahl an Attributen haben.
Zum Beispiel:

1 - A, B, C
2 - A, E
3 - B, C, I, K
4 - G, I
5 - B, E, K

Ich will jetzt auf irgend eine Art und Weise alle passenden Datensätze selektieren, deren Attribute sich komplett in der Vorgabenliste wiederfinden. Im obigen Beispiel wären das dann:
2, 4 und 5

Die Anzahl der Datensätze und Werte wird sich nicht großartig ändern. 10.000/100

Die dahinter liegende Architektur steht noch nicht fest. Am liebsten wäre mir eine kleine in Memory DB. Allerdings wäre auch ein Graphenmodell ala Neo4J eine Überlegung wert. Letztenendes muss es recht leichtgewichtig sein, da es auf meinem Smartphone laufen soll.

Aktuell sind die Datensätze noch in einer Textdatei persistiert.

Leider fällt mir momentan kein sinnvolles SQL Statement o.Ä. ein mit dem ich das "Problem" performant lösen kann. Evtl. habt ihr ja eine Idee oder gebt mir den fehlenden Anstoß zur Lösung des Knotens. Ich zermarter mir jetzt schon etliche Abende damit den Kopf :rolleyes:
 
Zuletzt bearbeitet:
http://sqlfiddle.com/#!9/f9f1a/5
Code:
CREATE TABLE nums (
	nums_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT
);

CREATE TABLE attr (
	attr_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
	num_id INT NOT NULL,
	`key` varchar(32) NOT NULL
);

INSERT INTO nums VALUES (NULL);
SELECT LAST_INSERT_ID() INTO @id;
INSERT INTO attr (num_id,`key`) VALUES (@id, 'A'), (@id, 'B'),(@id,'C');

INSERT INTO nums VALUES (NULL);
SELECT LAST_INSERT_ID() INTO @id;
INSERT INTO attr (num_id,`key`) VALUES (@id,'A'),(@id,'E');

INSERT INTO nums VALUES (NULL);
SELECT LAST_INSERT_ID() INTO @id;
INSERT INTO attr (num_id,`key`) VALUES (@id,'B'),(@id,'C'),(@id,'I'),(@id,'K');

INSERT INTO nums VALUES (NULL);
SELECT LAST_INSERT_ID() INTO @id;
INSERT INTO attr (num_id,`key`) VALUES (@id,'G'),(@id,'I');

INSERT INTO nums VALUES (NULL);
SELECT LAST_INSERT_ID() INTO @id;
INSERT INTO attr (num_id,`key`) VALUES (@id, 'B'), (@id, 'E'),(@id,'K');




SELECT nums_id
FROM nums n
	JOIN attr a
		ON n.nums_id = a.num_id
WHERE
	num_id NOT IN(
		SELECT num_id
		FROM attr sa
			LEFT JOIN (
				SELECT 'A' `key`
				UNION SELECT 'B' `key`
				UNION SELECT 'E' `key`
				UNION SELECT 'G' `key`
				UNION SELECT 'I' `key`
				UNION SELECT 'K' `key`
				-- UNION ...
			) sb ON sa.`key` = sb.`key`
		WHERE sb.`key` IS NULL
		GROUP BY num_id
	)
GROUP BY nums_id
Keine Ahnung wie es um die Performance bei 10.000 Einträgen steht.
 
Super, danke.

Hab das mal fix implementiert und mit Realdaten befüllt.

12.000 Datensätze und rund 900 verschiedene Attribute.

Ein SELECT mit vier gegebenen Attributen benötigt auf meinem Laptop nur ~250ms. Das ist akzeptabel, selbst wenn es auf dem Smartphone 1 - 2 Sekunden braucht.
Ergänzung ()

Lassen sich diese Unions mit LIKE Selects in deinem Statement kombinieren?

Meine Attribute heißen ja nicht wirklich A, B, C, ... und in manchen Fällen würde ich AttributA, AttributB, AttributC gerne zusammenfassen und einfach LIKE 'Attr%' abfragen.

Die Frage ist dann aber auch, ob nicht ein LIKE Statement auf ein varchar(255) Feld langsamer ist als 10 weitere UNIONS hinzuzufügen. Index auf diesem Feld vorausgesetzt.
 
Zuletzt bearbeitet:
Zurück
Oben