Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [ROZWIĄZANY]Problem z pobieraniem danych + funkcja
Forum PHP.pl > Forum > Bazy danych > MySQL
krun
Witam.

Mam następujący problem.
Napisałem sobie funkcje, która z kilku tabel wyciąga jedną wartość i to działa ładnie, zapytanie zwraca taki wynik:

Kod
+---+---+---+
| a | b | c |
+---+---+---+
| 1 | 1 | 3 |
+---+---+---+
| 4 | 1 | 1 |
+---+---+---+
| 5 | 1 | 1 |
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 4 | 2 | 1 |
+---+---+---+
| 5 | 2 | 1 |
+---+---+---+
| 1 | 3 | 3 |
+---+---+---+
| 4 | 3 | 1 |
+---+---+---+
| 5 | 3 | 1 |
+---+---+---+


a i b to wartości pobierane bezpośrednio z bazy danych, c to wartość pobierana z funkcji, i teraz moje pytanie - dlaczego jeśli przyrównam b z c(z funkcją to zwracane są tylko 2 wartości? 4-1-1 i 5-1-1, powinna zostać zwrócona jeszcze wartość 1-3-3 w końcu tu też b-c!

Ps.
Przepraszam za mało precyzyjny temat, ale nie wiedziałem jak to zatytułować.
nevt
pokaż to porównanie - pokaż tą funkcję - mamy wrózyć z fusów czy z tej tabelki co pokazałeś (to się chyba nazywa numerologia czy jakoś tak...) questionmark.gif
krun
Funkcja wygląda tak:

  1. CREATE FUNCTION `znajdz_id_do_wyslania`(`inpt_email_id` INT, `inpt_data` TIMESTAMP) RETURNS int(11) UNSIGNED
  2. BEGIN DECLARE `w` INT(11);
  3. DECLARE `p` INT(11);
  4. DECLARE `i` INT(11);
  5.  
  6. SET `w` = (SELECT `wyslane`.`id` FROM `wyslane` WHERE `wyslane`.`id_emaila`=`inpt_email_id`
  7. ORDER BY `wyslane`.`data` DESC LIMIT 1 );
  8.  
  9. IF (SELECT `wyslane`.`data` FROM `wyslane` WHERE `wyslane`.`id`=`w`) <= `inpt_data` THEN
  10. SET `p` = (SELECT `listy`.`priorytet` FROM `listy`, `wyslane`
  11. WHERE `wyslane`.`data` <= `inpt_data` AND `wyslane`.`id_listu`=`listy`.`id` AND `wyslane`.`id_emaila`=`inpt_email_id`
  12. ORDER BY `wyslane`.`id` DESC LIMIT 1 );
  13. ELSEIF `w` IS NULL THEN
  14. SET `p`=0;
  15. ELSE
  16. RETURN NULL;
  17. END IF;
  18.  
  19. SET `p` = (`p` + 1);
  20.  
  21. SET `i` = (SELECT `listy`.`id` FROM `listy` WHERE `listy`.`priorytet`=`p`);
  22.  
  23. RETURN `p`;
  24.  
  25. END


Zapytanie tak
  1. SELECT `emaile`.`id`, `listy`.`id`, znajdz_id_wyslanego(`emaile`.`id`, 'jakas-data')
  2. FROM `listy`, `emaile` WHERE `listy`.`id`=znajdz_id_wyslanego(`emaile`.`id`, 'data-ta-sama-co wczesniej')


A tabele tak:

  1. CREATE TABLE `emaile` (
  2. `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `data` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  4. `email` varchar(256) NOT NULL,
  5. `klucz` varchar(20) NOT NULL,
  6. PRIMARY KEY (`id`),
  7. UNIQUE KEY `unq` (`email`)
  8. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
  9.  
  10. CREATE TABLE `listy` (
  11. `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  12. `temat` varchar(500) NOT NULL,
  13. `tresc` longtext NOT NULL,
  14. `priorytet` int(11) NOT NULL,
  15. PRIMARY KEY (`id`)
  16. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
  17.  
  18. CREATE TABLE `wyslane` (
  19. `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  20. `id_emaila` int(10) UNSIGNED NOT NULL,
  21. `id_listu` int(10) UNSIGNED NOT NULL,
  22. `data` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  23. PRIMARY KEY (`id`),
  24. UNIQUE KEY `unq` (`id_emaila`,`id_listu`)
  25. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;


Ale dziwne dla mnie jest to, że 3 != 3!

Przepraszam za natarczywość, ale bardzo zależy mi na odpowiedzi. Ma ktoś pojęcie czym mój problem może być spowodowany?
nevt
szczerze mówiąc wszystko wydaje sie być ok. ... dziwne...

co prawda twoja funkcja zwraca liczbę typu int(11) którą porównujesz z polem id typu int(10) unsigned ... ale zasadniczo nie powinno to mieć znaczenia dla wyniku porównania, na wszelki wypadek jednak spróbuj zmienić funkcję tak, żeby też zwracała int(10) unsigned ...

a drugie podejrzenie, to dwukrotne wywołanie twojej funkcji w każdym wierszu zapytania ... teoretycznie nie powinno mieć to wpływu na rezultat ale na pewno nie jest wydajne... spróbuj zmienić zapytanie na coś w rodzaju:
  1. SELECT `emaile`.`id`, `listy`.`id`, znajdz_id_wyslanego(`emaile`.`id`, 'jakas-data') AS`znalezione_id` FROM `listy`, `emaile` WHERE `listy`.`id`=`znalezione_id`;
krun
Sprawdziłem, nie działa. Ale najdziwniejsze jest to, że jak porównuje to z liczbami wprowadzonymi ręcznie czyli znajdz_id_wyslanego()=2 to też jest to falsz. działa tylko w przypadku liczby 1. Ktoś zna możliwy powód?

Druga sprawa

Cytat(nevt @ 21.06.2008, 22:38:48 ) *
drugie podejrzenie, to dwukrotne wywołanie twojej funkcji w każdym wierszu zapytania ... teoretycznie nie powinno mieć to wpływu na rezultat ale na pewno nie jest wydajne... spróbuj zmienić zapytanie na coś w rodzaju:
  1. SELECT `emaile`.`id`, `listy`.`id`, znajdz_id_wyslanego(`emaile`.`id`, 'jakas-data') AS`znalezione_id` FROM `listy`, `emaile` WHERE `listy`.`id`=`znalezione_id`;


To nie działa,
Cytat
Nie znaleziono kolumny 'znalezione_id' w where clause.


Ale przy pojedynczym wywołaniu funkcji też nie zwraca tych wyników które powinien, więc na pewno nie jest to wina podwójnego wywołania a mój błąd gdzieś w funkcji.. Tylko kto mi powie jaki?
osiris
Czy w definicji funkcji `znajdz_id_wysylanego` nie powinenes przypadkiem uzywac zmiennych o identyfikatorach poprzedzonych znakiem @?

Tj.
  1. DECLARE @w INT;
  2.  
  3. SET @w = (SELECT ....);
  4. ...


Pozdrawiam
krun
Cytat(osiris @ 25.06.2008, 22:49:07 ) *
Czy w definicji funkcji `znajdz_id_wysylanego` nie powinenes przypadkiem uzywac zmiennych o identyfikatorach poprzedzonych znakiem @?

Tj.
  1. DECLARE @w INT;
  2.  
  3. SET @w = (SELECT ....);
  4. ...


Pozdrawiam


Nie wydaje mi się. Dlaczego miałbym ich używać?

Problem rozwiązał się właściwie sam... Na innym systemie próbowałem wrzucić tą funkcje i zostałem poproszony o dodanie do niej dwóch linijek:
  1. READS SQL DATA
  2. DETERMINISTIC


Sama funkcja powinna wyglądać tak:
  1. CREATE FUNCTION `znajdz_id_do_wyslania`(`inpt_email_id` INT, `inpt_data` TIMESTAMP) RETURNS int(11) UNSIGNED
  2. READS SQL DATA
  3. DETERMINISTIC
  4. BEGIN DECLARE `w` INT(11);
  5. DECLARE `p` INT(11);
  6. DECLARE `i` INT(11);
  7.  
  8. SET `w` = (SELECT `wyslane`.`id` FROM `wyslane` WHERE `wyslane`.`id_emaila`=`inpt_email_id`
  9. ORDER BY `wyslane`.`data` DESC LIMIT 1 );
  10.  
  11. IF (SELECT `wyslane`.`data` FROM `wyslane` WHERE `wyslane`.`id`=`w`) <= `inpt_data` THEN
  12. SET `p` = (SELECT `listy`.`priorytet` FROM `listy`, `wyslane`
  13. WHERE `wyslane`.`data` <= `inpt_data` AND `wyslane`.`id_listu`=`listy`.`id` AND `wyslane`.`id_emaila`=`inpt_email_id`
  14. ORDER BY `wyslane`.`id` DESC LIMIT 1 );
  15. ELSEIF `w` IS NULL THEN
  16. SET `p`=0;
  17. ELSE
  18. RETURN NULL;
  19. END IF;
  20.  
  21. SET `p` = (`p` + 1);
  22.  
  23. SET `i` = (SELECT `listy`.`id` FROM `listy` WHERE `listy`.`priorytet`=`p`);
  24.  
  25. RETURN `p`;
  26.  
  27. END


Dziękuje wszystkim którzy starali się mi pomóc.
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.