Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Wyszukiwanie najbardziej pasujących szeregów danych.
Forum PHP.pl > Forum > Bazy danych > MySQL
eshlox
Witam.

Ostatnio tak myślę nad jednym zapytaniem, lub kilkoma.. lub czymkolwiek.. co prawdopodobnie będę potrzebował. Nie mogę jakoś wymyślić nic sensownego. Aczkolwiek, nie jest to chyba proste zadanie ;-)

Powiedzmy, że mamy taką tabelę mysql:

id | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | n

Id standardowo będzie zwiększane o 1 przy dodawaniu nowego szeregu danych, a w komórkach 1,2,3 itd będą wstawiane tylko i wyłącznie cyfry typu INT. Prawdopodobnie przedział od 1 - 9, chociaż myślę, że nie ma to tutaj znaczenia. Jak widać na końcu dałem n, bo z czasem ilość kolumn tabeli może się zwiększać o dalsze, nazwane n+1 i także zawierające INT.
Więc dajmy na to, niech na początku będzie id i 8 kolumn odnośnie danych. (i = id, skróciłem aby "tabela" była równa ;-))

i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
1 | 3 | 3 | 3 | 0 | 1 | 3 | 2 | 1
2 | 2 | 2 | 5 | 1 | 2 | 9 | 5 | 2
3 | 3 | 3 | 3 | 0 | 2 | 4 | 1 | 5
4 | 3 | 3 | 3 | 4 | 1 | 3 | 2 | 0

I teraz główna kwestia. Wybieramy sobie jakiś szereg, np. o id 1 i według niego szukamy n najbardziej pasujących do niego. Czyli tutaj dla przykładu, najwięcej zgadza się z szeregiem 4, bo 75% liczb w kolumnach się pokrywa, później szereg 3 - 50% no i na końcu szereg 2, który ma 0% zgodności. Limit to np. 10 najbardziej trafnych wyników. Wszystko posortowane od najtrafniejszego do najmniej trafnego. I także wynik procentowy względem każdego wyszukanego wyniku. (Wiadomo także, że może się okazać, iż jest więcej szeregów pasujących procentowo.)

Mam nadzieję, że każdy zrozumie o co mi chodzi ;->

Jakby ktoś miał pomysły, jak takie coś uzyskać, to chętnie posłucham ;-)

Pozdrawiam.
jmail
nie mogłeś wymyślić bardziej skomplikowanego sposobu na zabicie mysql'a? haha.gif

W Windows wchodzisz menu start -> panel sterowania -> narzędzia administracyjne -> usługi -> prawym przyciskiem na mysql -> stop

a na przykłąd w ubuntu wpisujesz w terminal

sudo /etc/init.d/mysql stop

po pierwsze musiałbyś zmienić nazwy kolumn. na przykłąd nadać im przedrostek c bo inaczej się może wykrzaczyć. Ale ok na razie zostaw jak jest ;P
po drugie musiałbyś utworzyć procedurę mysql, która w pętli "przeleci" to za ciebie tongue.gif

Po nie wiem dwóch godzinach intensywnego kodu biggrin.gif

  1.  
  2. DELIMITER $$
  3.  
  4. DROP PROCEDURE IF EXISTS ZabijMySQLfunc $$
  5. CREATE DEFINER=`root`@`%` PROCEDURE ZabijMySQLfunc(IN iloscKolumn int,IN iloscWynikow int,IN wzorcowyWiersz int)
  6.  
  7. BEGIN
  8.  
  9. SET @iloscWynikow = iloscWynikow;
  10.  
  11. CREATE TEMPORARY TABLE IF NOT EXISTS
  12. wyniki
  13. (
  14. idWiersza int NOT NULL PRIMARY KEY
  15. ,iloscDopasowan int NOT NULL DEFAULT 0
  16. );
  17. INSERT INTO
  18. wyniki
  19. (idWiersza)
  20. SELECT
  21. id
  22. FROM
  23. tabelaWzorcowa
  24. WHERE
  25. id <> wzorcowyWiersz;
  26.  
  27. SET @iloscPrzebiegow = 0;
  28.  
  29. etykieta1: LOOP
  30. IF @iloscPrzebiegow < iloscKolumn THEN
  31. SET @iloscPrzebiegow = @iloscPrzebiegow + 1;
  32. SET @kolumna1 = concat('`t1`.`',@iloscPrzebiegow,'`');
  33. SET @kolumna2 = concat('`t2`.`',@iloscPrzebiegow,'`');
  34.  
  35. UPDATE
  36. wyniki
  37. SET
  38. iloscDopasowan = iloscDopasowan + 1
  39. WHERE
  40. idWiersza IN
  41. (
  42. SELECT
  43. t2.id
  44. FROM
  45. tabelaWzorcowa t1
  46. INNER JOIN
  47. tabelaWzorcowa t2
  48. ON
  49. @kolumna1 = @kolumna2
  50. WHERE
  51. t1.id = wzorcowyWiersz
  52. );
  53. ITERATE etykieta1;
  54. END IF;
  55. LEAVE etykieta1;
  56. END LOOP etykieta1;
  57.  
  58. PREPARE STMT FROM 'SELECT idWiersza,iloscDopasowan FROM wyniki ORDER BY iloscDopasowan desc LIMIT ?';
  59. EXECUTE STMT USING @iloscWynikow;
  60.  
  61. DROP TABLE wyniki;
  62.  
  63. END $$
  64.  
  65. DELIMITER ;
  66.  


wywołujesz to

  1.  
  2. CALL ZabijMySQLfunc(tu wstawiasz parametry);
  3.  


I prośba - nie każ mi tego tłumaczyć. Kolejnego litra wódki nie zniosę biggrin.gif

//edit

no dobra przesadziłem biggrin.gif to była godzina 20 i litr też nie poszedł. mam jeszcze pół szklanki na dnie biggrin.gif
eshlox
Huh ;-) Jak tylko będę miał chwilę czasu to sprawdzę to.. Ale rzeczywiście gdy rekordów będzie dużo.. i gdyby takie coś wykonać jednoczenie ileś razy.. Muszę pomyśleć chyba nad lepszym rozwiązaniem takiego porównywania.

Ale dzięki za kod ;-)
jmail
może napisz do czego to potrzebujesz to może coś lepszego się wymyśli. ale niczego szybszego niż takie zapytanie nie wymyślisz. Jeżelimówimy o danych z bazy. Taką samą ilość zapytań bedziesz musiał wykonać przez PHP a przez bazę szybciej to pójdzie.
eshlox
No ja tylko szukam sposobu jak najlepiej dokonać takiego porównania. W sumie nawet te cyfry mogą być ułożone jedna po drugiej i zapisane jako ciąg w bazie danych. Ale czy to coś zmieni..
jmail
ale kurde do czego to potrzebujesz? co będziesz porównywał? rozmairy stóp czy co?
kitol
jeżeli przeprojektujesz tabelę do postaci trzech kolumn:

numer_serii
numer_pomiaru_w_serii,
wartosc_pomiaru

to rozwiazanie będzie prawie banalne:

  1. SELECT t1, SUM(dopasowanie)/COUNT(dopasowanie) FROM (
  2. SELECT b.t1, b.t3 = a.t3 dopasowanie FROM `test4` a
  3. JOIN (SELECT * FROM test4 WHERE t1!=1) b USING(t2)
  4. WHERE a.t1=1
  5. ) c GROUP BY t1


sprawdzane na tabeli:

  1. CREATE TABLE `test4` (
  2. `t1` int(10) UNSIGNED NOT NULL,
  3. `t2` int(10) UNSIGNED NOT NULL,
  4. `t3` int(10) UNSIGNED NOT NULL,
  5. PRIMARY KEY (`t1`,`t2`)
  6. ) ENGINE=MyISAM;
  7.  
  8. INSERT INTO `test4` (`t1`, `t2`, `t3`) VALUES
  9. (1, 1, 3),
  10. (1, 2, 3),
  11. (1, 3, 3),
  12. (1, 4, 0),
  13. (1, 5, 1),
  14. (1, 6, 3),
  15. (1, 7, 2),
  16. (1, 8, 1),
  17. (2, 1, 2),
  18. (2, 2, 2),
  19. (2, 3, 5),
  20. (2, 4, 1),
  21. (2, 5, 2),
  22. (2, 6, 9),
  23. (2, 7, 5),
  24. (2, 8, 2),
  25. (3, 1, 3),
  26. (3, 2, 3),
  27. (3, 3, 3),
  28. (3, 4, 0),
  29. (3, 5, 2),
  30. (3, 6, 4),
  31. (3, 7, 1),
  32. (3, 8, 5),
  33. (4, 1, 3),
  34. (4, 2, 3),
  35. (4, 3, 3),
  36. (4, 4, 4),
  37. (4, 5, 1),
  38. (4, 6, 3),
  39. (4, 7, 2),
  40. (4, 8, 0);
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.