Odkaz na předchozí a další záznam

Školení, která pořádám

Řekněme, že máme nějaký seznam záznamů řazený třeba podle názvu a v detailu každého záznamu chceme zobrazit informaci o tom, kolikátý v seznamu je, a odkaz na předchozí a následující záznam.

Pořadí záznamu

Pokud je základní dotaz SELECT * FROM `clanky` ORDER BY `nadpis`, můžeme pořadí zjistit dotazem SELECT COUNT(*) FROM `clanky` WHERE `nadpis` <= @nadpis, kde @nadpis je nadpis aktuálního článku. Problém vznikne v případě, kdy se dva články jmenují stejně – u nich se vrátí pořadí posledního článku daného jména.

Vyřešit se to dá přidáním nějakého unikátního sloupce do řazení i do podmínky: z ORDER BY `nadpis`, `id` vznikne WHERE (`nadpis`, `id`) <= (@nadpis, @id) nebo složitější WHERE `nadpis` < @nadpis OR (`nadpis` = @nadpis AND `id` <= @id). To také dává návod na to, jak postupovat při řazení podle více sloupců. U dotazů používajících agregaci lze dotaz zjišťující počet obvykle položit bez agregace. Pokud to nejde, lze to vyřešit poddotazem.

Odkaz na předchozí a následující záznam

Odkaz na předchozí záznam se dá zjistit dotazem SELECT * FROM `clanky` WHERE (`nadpis`, `id`) < (@nadpis, @id) ORDER BY `nadpis` DESC, `id` DESC LIMIT 1, odkaz na následující záznam obdobně. Pokud už máme zjištěné pořadí záznamu, dá se použít také "SELECT * FROM clanky ORDER BY nadpis, id LIMIT 1 OFFSET " . ($poradi - 2).

Jakub Vrána, Řešení problému, 27.3.2009, diskuse: 8 (nové: 0)

Diskuse

Kajman:

Já to vždy psal s or. Díky za tip, je to hned přehlednější.

Kajman:

Vypadá to, že verze s or nemá problém s využitím indexu na nadpisu. Takže bude možná rozdíl mezi "složitejším" z pohledu uživatele a serveru.

ikona Jakub Vrána OpenID:

V dokumentaci píšou, že ROW() je možno optimalizovat od 5.0.26 a 5.1.12: http://dev.mysql.com/doc/refman/5.0/en/row-subqueries.html

Kajman:

Explain byl rozdílný v or zápisu a row zápisu na verzi 5.0.60.

Kajman:

Ještě poznámka, že na operátor = to index použilo i v row zápisu, ale na < či > ne.

matak:

reagoval si na můj článek

http://www.webfaq.cz/clanek/Mysql-poradi-…#commentary294

já sem to řešil tak, aby bylo možné získat další záznam nezávisle na tom jak je současný výpis řazen, dokonce tak aby bylo možné získat předchozí a příští záznam z libovolného dotazu,

ten tvůj je založen na tom že znám předem podmínky řazení a porovnávám, ale vypadá to dobře

zvo:

Díky moc za návod, sám bych to asi nevymyslel.

emer:

ja pouzivam nieco taketo

SELECT nazov_clanku FROM clanky WHERE id > $id_aktulne_zobrazeneho_clanku ORDER BY id  LIMIT 1 #nasledujuci

SELECT nazov_clanku FROM clanky WHERE id < $id_aktulne_zobrazeneho_clanku ORDER BY id DESC LIMIT 1 #predosli

Diskuse je zrušena z důvodu spamu.

avatar © 2005-2024 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.