Get 20 most frequent groups of values

Am sa postez direct un screenshot cu o intrebare de pe stackoverflow, luat din google webcache pentru ca intrebarea a fost deja stearsa. Cum se poate rezolva acesta problema? Apropo, nu eu am postat intrebarea, dar as vrea sa stiu rezolvarea. Multumesc.

Ai invatat deja despre normalizare, asa cum ti s-a spus intr-un comentariu?

1 Like

Apropo, nu eu am postat intrebarea, dar sunt curios sa vad cum se poate rezolva. Am incercat varianta din comentarii, cu “normalizare”, asa cum zici tu, dar fara succes.

1 Like

Posteaza un dump in SQL al datelor normalizate (impreuna cu tabelele), ca sa ne fie mai usor sa te ajutam.

1 Like

data.zip (761 Bytes)

Îți lipsește o coloană.
În exemplul dat de tine cu numerele la loto, acea coloană ar reprezenta ID-ul extragerii.
Deasemenea, coloana nr_i este în plus; nu ai nevoie de ea atâta timp cât coloana id are AUTO_INCREMENT.

Îți propun următoarea structură:

Table: `data`
+----+----+-----+
| id | nr | set | 
+----+----+-----+
|  1 | 52 |   1 | 
|  2 | 47 |   1 | 
|  3 |  4 |   1 | 
|  4 |  3 |   1 | 
|  5 | 77 |   1 | 
|  6 | 71 |   1 | 
|  7 |  6 |   1 | 
|  8 | 41 |   1 | 
|  9 | 15 |   1 | 
| 10 | 79 |   1 | 
| 11 | 35 |   2 | 
| 12 | 50 |   2 | 
| 13 | 16 |   2 | 
| 14 |  1 |   2 | 
| 15 | 32 |   2 | 
| 16 | 77 |   2 | 
| 17 | 30 |   2 | 
| 18 |  7 |   2 | 
| 19 | 20 |   2 | 
| 20 | 28 |   2 | 
| .. | .. | ... | 
+----+----+-----+

Datele, așa cum le vrei tu, le poți extrage folosind query-ul:

SELECT 
    `n1`.`nr` AS `num_1`,
    `n2`.`nr` AS `num_2`,
    COUNT(1) AS `total`

FROM `data` AS `n1`

JOIN `data` AS `n2` 
    ON `n1`.`set` = `n2`.`set` AND `n1`.`nr` < `n2`.`nr`

GROUP BY `n1`.`nr`, `n2`.`nr`
ORDER BY `total` DESC
LIMIT 20

pentru 2 numere, iar pentru 3, mai adaugi un join din același tabel plus numele câmpului ce va fi selectat în secțiunile SELECT și GROUP BY și condiția de la JOIN ca numărul selectat să fie mai mare decât cel din JOIN-ul anterior (același lucru e valabil și dacă vrei un grup de 4 numere)

SELECT 
    `n1`.`nr` AS `num_1`,
    `n2`.`nr` AS `num_2`,
    `n3`.`nr` AS `num_3`,
    COUNT(1) AS `total`

FROM `data` AS `n1`

JOIN `data` AS `n2` 
    ON `n1`.`set` = `n2`.`set` AND `n1`.`nr` < `n2`.`nr`

JOIN `data` AS `n3` 
    ON `n1`.`set` = `n3`.`set` AND `n2`.`nr` < `n3`.`nr`

GROUP BY `n1`.`nr`, `n2`.`nr`, `n3`.`nr`
ORDER BY `total` DESC
LIMIT 20

Am folosit o colecție de 100.000 de intrări (10.000 de seturi a câte 10 numere aleatorii unice, adică circa 180 de ani de extrageri săptămânale :grinning:) pe mașina locală iar rezultatele au fost cam așa:

  • 2 numere: 4 secunde
  • 3 numere: 15 secunde
  • 4 numere: 60 secunde

Setul de date folosit: sample-data.zip (386.3 KB)

Rezultatul va fi de forma:

+-------+-------+-------+-------+
| num_1 | num_2 | num_3 | total | 
+-------+-------+-------+-------+
|    25 |    40 |    76 |    33 | 
|     7 |    18 |    35 |    33 | 
|    46 |    59 |    60 |    32 | 
|    62 |    70 |    75 |    32 | 
|    14 |    23 |    47 |    32 | 
|    38 |    69 |    76 |    31 | 
|  ...  |  ...  |  ...  |  ...  |
+-------+-------+-------+-------+

Pentru a verifica corectitudinea, poți folosi

SELECT COUNT(1) FROM `data` WHERE
    `nr` = 25 AND `set` IN (SELECT `set` FROM `data` WHERE
    `nr` = 40 AND `set` IN (SELECT `set` FROM `data` WHERE
    `nr` = 76))

P.S.: La JOIN, a doua condiție (n1.nr < n2.nr) este pentru a te asigura că este luat în cosiderare fiecare grup de numere din același set o singură dată, adică [7, 35], dar nu și [35, 7] sau [25, 40, 76], dar nu [25, 76, 40] ori [40, 25, 76]. Matematic vorbind, fără condiția aia, în urma JOIN-urilor ar rezulta n2 rânduri pentru fiecare set, în timp ce nouă ne trebuie combinări ne n luate câte k (Cnk).

9 Likes

Un big like din partea mea. Multumesc mult.

1 Like

Salut Ionut! Crezi ca ai putea sa ma ajuti in privat contra cost la cateva interogari de genul ? PS. Eu postasem problema pe stackoverflow. Merci.

te pot ajuta si eu

Spune-mi cum te pot contacta.

YM: angel_petrescu, Skype: angel.petrescu

Pe aceeasi structura de db, se poate afla cumva Top Remize Istorice 3/3 ?

Top Remize Istorice 3/3 = topul tripletelor(3/3) cu cele mai MARI remize atinse de la prima extragere şi până în prezent.

Remiza reprezintă numărul consecutiv de extrageri în care un număr sau o combinaţie de numere nu a fost extrasă.