Autor Zpráva
velkej
Profil
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
Ty jo. Čeho chceš přesně dosáhnout?
bohyn
Profil
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
Č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
Jo sem zapomněl říct, že ID je primární klíč, UNIQUE INDEX ... jinak by to nebyla žádná záhada samozřejmě :-)
sicario
Profil
A co vraceji jednotlive subdotazy?
Kajman_
Profil *
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
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
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
Btw. nachytal se i kolega v praci stejne jako ja na ten muj dotaz, dal jsem mu to jako hadanku :)
Toto téma je uzamčeno. Odpověď nelze zaslat.

0