Autor | Zpráva | ||
---|---|---|---|
velkej Profil |
#1 · Zasláno: 20. 1. 2009, 18:31:40
Ahoj,
zkousel jsem si tak ruzne dotazy s nahodnym cislem. Jak jsem si tak hral spustil jsem tohle: SELECT * FROM msgboard WHERE id = ( SELECT (SELECT MIN(ID) FROM msgboard) + FLOOR((SELECT MAX(ID) FROM msgboard) * RAND()) ) a k memu velkemu prekvapeni mi to vratilo nekdy i 2 ci 3 radky. Priznam se, ze sem z toho tumpachovej. Jak je mozny, ze to nevrati bud jeden nebo zadny radek ? Ale treba 3 radky (ID 34198, 25213 a 61690) ? Diky za jakykoliv tip :) Pavel ps. MySQL: 5.0.26, phpMyAdmin 3.1.2-rc1, OS Gentoo |
||
pifko Profil |
#2 · Zasláno: 20. 1. 2009, 18:54:41
Ty jo. Čeho chceš přesně dosáhnout?
|
||
bohyn Profil |
#3 · Zasláno: 20. 1. 2009, 19:02:27
pifko
„Čeho chceš přesně dosáhnout?“ Daleko zajimavejsi je ceho dosahl :) Zkousel jsem EXPLAIN a myslim ze MySQL z toho taky neni zrovna nejchytrejsi. Kuprikladu vyradi indexy (vubec je nevypise jako mozne), proc? |
||
velkej Profil |
#4 · Zasláno: 20. 1. 2009, 19:02:34
Čeho se tím SELECTem má dosáhnout není důležitý, říkám, jsem si tak hrál z dlouhé chvíle. Ale jestli někdo budete mít vysvětlení pro tenhle zvláštní jev, to jsem hrozně zvědavej :-)
|
||
velkej Profil |
#5 · Zasláno: 20. 1. 2009, 19:07:01
Jo sem zapomněl říct, že ID je primární klíč, UNIQUE INDEX ... jinak by to nebyla žádná záhada samozřejmě :-)
|
||
sicario Profil |
#6 · Zasláno: 20. 1. 2009, 19:44:09
A co vraceji jednotlive subdotazy?
|
||
Kajman_ Profil * |
#7 · Zasláno: 20. 1. 2009, 20:25:38
Není to žádná záhada, když se dělá where neco in (select..), tak se ten select porovnává s každým řádkem, ale pokaždé se bude vypočítávat znovu - díky rand budou pro každý řádek náhodné hodnoty k porovnání.
I z výkonostních ohledů je proto lepší psát takové poddotazy jako spojení... SELECT m.* FROM msgboard m, ( SELECT MIN(ID)+FLOOR(MAX(ID)* RAND()) as id FROM msgboard ) t WHERE m.id = t.id A ještě lepší je udělat náhodný limit, id nemusí být bez mezer. |
||
velkej Profil |
#8 · Zasláno: 20. 1. 2009, 21:49:29 · Upravil/a: velkej
Kdyby bylo IN tak jo, o tom žádná, ale já tam nemam IN, je tam = ...
A dotaz SELECT (SELECT MIN(ID) FROM msgboard) + FLOOR((SELECT MAX(ID) FROM msgboard) * RAND()) vrací vždy jen jeden řádek, jeden sloupec coby číslo. A dotaz SELECT * FROM msgboard WHERE id = ( 63634 ) pak podle mě logicky může vrátit leda 0 nebo 1 řádek. Jinak ten dotaz jak jsi ho napsal Ty samozřejmě může vracet 0 až n řádků (join dvou tabulek). Jak jsi psal kdyby můj dotaz byl s IN a vracel více řádků, vypadalo by to takhle: SELECT * FROM msgboard WHERE id IN /* = */ ( SELECT (SELECT MIN(ID) FROM msgboard) + FLOOR((SELECT MAX(ID) FROM msgboard) * RAND()) ) Jinak co se týče subdotazů jak zněla otázka tak agregační funkce MIN() a MAX() vrací pouze jednu hodnotu. SELECT MIN(ID) FROM msgboard ... vrátí jeden řádek o jednom sloupečku, buď číslo nebo je-li počet řádků v tabulce msgboard 0, pak NULL. Stejné je to s SELECT MAX(ID) FROM msgboard. Výsledek se násobí náhodným číslem. Na tento výsledek se použije FLOOR(x), který vrací největší celočíselnou hodnotu nižší než x. Výsledek je jedno číslo. To se sečte s tím, co vrací MIN(). Takže výsledek subselectu může být jen jedno číslo. http://dev.mysql.com/doc/refman/5.1/en/mathematical-functions.html#function_floor http://dev.mysql.com/doc/refman/5.0/en/mathematical-functions.html#function_round http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_max http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_min |
||
Kajman_ Profil * |
To co platí pro where neco in (poddotaz) platí i pro where neco = (poddotaz) a dokonce i pro všechny jiné něco operátor (poddotaz). Poddotaz se pro vyhodnocení podmínky počítá pro každý řádek znovu!
I podle explain byste měl pochopit, že náhodné číslo se vypočítá jedno, ale tolikrát, kolik je v tabulce řádků - pro každý řádek znovu a s touto hodnotou se ten řádek porovnává. Jestli nehovíte explain, tak alespoň zkuste dotaz na tabulce s miliónem řádků, tam by to mělo být znát každému. Jinak ten dotaz jak jsi ho napsal Ty samozřejmě může vracet 0 až n řádků (join dvou tabulek). Zkoušel jste ho a píše více než jeden řádek? Já ho nezkoušel, ale podle selského rozumu by to mělo vracet více řádku jen není-li id unikátní. |
||
velkej Profil |
#10 · Zasláno: 21. 1. 2009, 11:03:49
„To co platí pro where neco in (poddotaz) platí i pro where neco = (poddotaz) a dokonce i pro všechny jiné něco operátor (poddotaz). Poddotaz se pro vyhodnocení podmínky počítá pro každý řádek znovu!“
„I podle explain byste měl pochopit, že náhodné číslo se vypočítá jedno, ale tolikrát, kolik je v tabulce řádků - pro každý řádek znovu a s touto hodnotou se ten řádek porovnává. Jestli nehovíte explain, tak alespoň zkuste dotaz na tabulce s miliónem řádků, tam by to mělo být znát každému.“ „Jinak ten dotaz jak jsi ho napsal Ty samozřejmě může vracet 0 až n řádků (join dvou tabulek).“ „Zkoušel jste ho a píše více než jeden řádek? Já ho nezkoušel, ale podle selského rozumu by to mělo vracet více řádku jen není-li id unikátní.“ Máte pravdu :-) Vyhodnocuje se to pro každý řádek znova. Ty náhodná čísla ... ty mě zmátly teda :)) Takže je po záhadě. Díky. |
||
velkej Profil |
#11 · Zasláno: 21. 1. 2009, 11:31:02
Btw. nachytal se i kolega v praci stejne jako ja na ten muj dotaz, dal jsem mu to jako hadanku :)
|
||
Časová prodleva: 15 let
|
Toto téma je uzamčeno. Odpověď nelze zaslat.
0