PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Kombinationen speichern und abfragen



Waxolunist
17-02-2007, 17:47
Hallo

Ich steh irgendwie an. Kann mir jemand weiterhelfen?

Folgendes Szenario.

Ich habe ca. 50 verschiedene Elemente und muß sehr oft Kombinationen berechnen aus verschieden vielen Elementen.

Ich will nun alle Kombinationen mit 5 aus 50 Elementen speichern und mir dann z.B. alle Kombinationen heraussuchen welche Elemente A3 und C4 enthalten.

Is also ein bissal wie Lotto.

Ich erhoffe mir aus dem Speichern einen Geschwindigkeitsvorteil gegenüber dem Berechnen, aber ich weiß leider nicht so recht, wie ich am besten diese kombinationen speichere und abfrage.

Weiß da jemand was?

mfg, Christian

Waxolunist
17-02-2007, 19:17
Zur Veranschaulichung noch ein kleines Beispiel mit MySQL.

Ich erzeuge eine Tabelle mit den Ids der Elemente:


CREATE TABLE `poker`.`elements_test` (
`id` TINYINT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY(`id`)
)
ENGINE = MYISAM;


Dann füge ich die IDs ein


insert into elements_test values(1);
insert into elements_test values(2);
insert into elements_test values(3);
insert into elements_test values(4);
insert into elements_test values(5);


Frage ich nun alle Kombinationen ab

select distinct * from elements_test t1, elements_test t2;
bekomme ich leider nicht nur alle Kombinationen sonder auch alle Permutationen.

Bekommen möchte ich aber nur folgendes:

12
13
14
15
23
24
25
34
35
45

Meine Abfrage ergibt aber 25 Ergebnisse.

mfg, Christian

Turbohummel
18-02-2007, 08:38
select t1.id id1, t2.id id2 from elements_test t1, elements_test t2
GROUP BY t1.id, t2.id


Ohne Garantie dass das irgendeinen Sinn ergibt.

Waxolunist
18-02-2007, 10:55
Ja, das ist leider das selbe wie meine Abfrage in grün. Alle Kombinationen, sowie deren Permutationen.

Waxolunist
18-02-2007, 12:12
Ich habe jetzt alle 5er Kombinationen in eine Tabelle gespeichert.


CREATE TABLE `elementscomb`.`elements5` (
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`element1` TINYINT UNSIGNED NOT NULL DEFAULT 0,
`element2` TINYINT UNSIGNED NOT NULL DEFAULT 0,
`element3` TINYINT UNSIGNED NOT NULL DEFAULT 0,
`element4` TINYINT UNSIGNED NOT NULL DEFAULT 0,
`element5` TINYINT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY(`id`),
INDEX `hand`(`element1`, `element2`, `element3`, `element4`, `element5`)
)
ENGINE = MYISAM;

Um nun alle Kombinationen mit den Elementen 2 und 3 abzufragen tätige ich nun folgende Abfrage:


SELECT * from elements5 where (element1=2 or element2=2 or element3=2 or element4=2 or element5=2) and (element1=3 or element2=3 or element3=3 or element4=3 or element5=3);

Das ist zwar im Moment eine gangbare Lösung (vor allem mit autogenerierten Abfragen), aber dass muss doch irgendwie besser gehen, oder?

Vor allem Abfrageperformance sollte irgendwie gesteigert werden und Speicherplatzmäßig ist es irgendwie nicht so richtig gut.
Die Tabelle hat jetzt bei ca. 50 Elementen ungefähr 2,6 Mio. rows. Bei 6 aus 50 oder 7 aus 50 wird das noch schlimmer.

Hat da jemand eine Idee?

mfg, christian

paule
18-02-2007, 21:33
> Meine Abfrage ergibt aber 25 Ergebnisse.
Dir fehlt die where-Klausel:


SELECT * FROM elements_test t1, elements_test t2
WHERE t1.id < t2.id;
Ergibt bei mir die von dir gewünschten 10 Ergebnissse. Läßt sich dann natürlich auf 5 Elemente erweitern.
elements_test muß nach den Id's sortiert sein, notfalls eine View erstellen.

Gruß,
Paul

Waxolunist
19-02-2007, 10:14
Thx, das war der entscheidende Hinweis.

Meine Abfrage sieht nun bei 5 aus x Elementen folgendermaßen aus:



select c1.num, c2.num, c3.num, c4.num, c5.num from
combination c1, combination c2, combination c3, combination c4, combination c5
where
c1.num < c2.num and
c2.num < c3.num and
c3.num < c4.num and
c4.num < c5.num and
(c1.num=2 or c2.num=2 or c3.num=2 or c4.num=2 or c5.num=2) and
(c1.num=3 or c2.num=3 or c3.num=3 or c4.num=3 or c5.num=3);


Diese Abfrage kann man nun sehr leicht automatisiert zusammenstellen und schwupps habe ich alle Kombinationen. Ich muss jetzt noch ein wenig mit Indices arbeiten um zu sehen, wie sich die Performance verhält bei dieser Lösung und bei der Lösung die ich oben schon gepostet habe, wobei letztere natürlich wesentlich mehr Arbeit macht als diese.