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

Ř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, on-line

Diskuse

Kajman:

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

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.
27.3.2009 03:34:22

ikona Jakub Vrána:

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
27.3.2009 06:21:59

Kajman:

Explain byl rozdílný v or zápisu a row zápisu na verzi 5.0.60.
27.3.2009 12:05:14

Kajman:

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

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

27.3.2009 11:52:57

zvo:

Díky moc za návod, sám bych to asi nevymyslel.
18.12.2009 19:11:34

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
6.7.2011 14:10:32
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.