Odkaz na další záznam

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

Pokud na stránce chceme zobrazovat odkazy na další a předcházející záznam, obvykle u posledního záznamu skončíme. Jak však postupovat v případě, že na konci chceme skočit opět na první záznam? Samozřejmě je možné položit dva dotazy, dá se to ale zvládnout i jedním:

SELECT id, nazev FROM odkazy ORDER BY poradi <= @poradi, poradi LIMIT 1

Nejprve se vezmou záznamy následující po aktuálním ve vzestupném pořadí a potom záznamy před aktuálním, také ve vzestupném pořadí.

Dlužno podotknout, že tento dotaz neumožní využití případného indexu nad sloupcem poradi, takže u velkých tabulek není nejvhodnější. U malých by měl být díky položení jediného dotazu naopak rychlejší.

Přijďte si o tomto tématu popovídat na školení Návrh a používání MySQL databáze.

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

Diskuse

Tomas Fejfar:

OK, timhle vybereme jeden odkaz ale neslo by neco jako:

<?php
$query
= "SELECT id, nazevm, (id-1) AS predchozi, (id+1) AS nasledujici FROM zpravy ORDER BY id";
?>

...takze bysme v kazdem row meli ID nasledujici polozky...?

Arcao:

Mozna pres union spojit tri selecty.

Ronnie:

Šlo by to za předpokladu, že z tabulky nikdy nebudete mazat záznamy, pokud ano, záznamy id-1 a id+1 nemusí existovat...

Tomas Fejfar:

Proto sem tam napsal to "něco jako" :) Takhle to můžu ošetřit až v kódu. Tim "id+1" jsem myslel odkaz na předchozí ID, nevěděl sem jak to jinak zapsat.

legoxx:

V case generovania stranky nie je mozne urcit predchadzajuci a nasledujuci zaznam kedze tieto id-cka sa moznu medzi generovanim a kliknutim na linku zmenit (zmazany zaznam, pridany zaznam).

Preto pouzivam relativne linky nieco ako

<a href=?id=32&type=prev>predchadzajuci</a>
<a href=?id=32>aktualny</a>
<a href=?id=32&type=next>nasledujuci</a>

a konkretna hodnota id sa zisti az pri jej skutocnom pouziti. Tato metoda vyzaduje vzdy iba jeden select na DB bez unionov.

ikona Jakub Vrána OpenID:

Já jsem kdysi u jednoho projektu dělal něco podobného - po vyhledávání jsem si přenášel seznam nalezených ID. Co kdyby náhodou nějaký záznam přibyl, ubyl nebo třeba změnil kategorii?

Problém s těmito odkazy je v tom, že vytvářejí duplicity pro vyhledávače. Jedna stránka je k dispozici přinejmenším na třech URL.

Takže i když mi toto řešení přijde elegantní, tak není moc praktické. Obvykle se také záznamy nemění tak rychle, aby to bylo potřeba řešit.

Pavel Zbytovský:

Mimochodem, tak to má, nebo alespoň měla řešená MediaWiki, tedy Wikipedie. Bylo to při procházení verzemi, zkrátka šetření dotazama na úkor vyhledávačů, jenže v tomto případě vlastně ani není žádoucí, aby to vyhledávač indexoval vysoko, takže to je ještě více ospravedlnitelné.

ikona dgx:

> Obvykle se také záznamy nemění tak rychle, aby to bylo potřeba řešit.

Ono "obvykle" může být zrádné ;-)

Podobně fungují třeba komentáře na La Trine. Když někdo píše komentář a odkazuje se na předchozí (např. [1].. [3]..), tak společně s komentářem se odešlou i skutečná ID, takže pokud během psaní nějaký komentář smažu, nedojde k rozhození odkazů. A samozřejmě si ID pamatuje ji nadále. Kdo maže, ten jede, ...ehm... ten by to měl řešit.

ikona D1ce:

IMHO pokud se o chybě dozvíš, "obvykle" ji i vyřešíš.

Pozn. Toto jsem nemyslel jako narážku na funkčnost(byť minulou) komentování na La Trine(děkuji moc za pěkný obsah), které mohlo být již po napsání bez chyb.

Jakub Podhorský:

jestli to dobře chápu tak pokud během psaní smažeš nějakej komentář na kterej odkazuju tak já ten komentář s tím smazaným ID odešlu ale odkaz se mi při zobrazení na něj neukáže? ale text zůstane?

ikona dgx:

Ani na něj nemusíš odkazovat, stačí že odkazuješ na jakýkoliv komentář za ním následující. Protože než komentář odešleš, číselná řada se posune.

Jakub Podhorský:

jo jasný ale mě de o to co v takovým případě s tím komentářem uděláš? nebo s tou částí která se na něco smazanýho odkazuje

ikona dgx:

Odkaz je pak neaktivní, zůstává v původní zapsané podobě.

Jakub Podhorský:

aha :) díky jen jsem chtěl tak nějak vědět jak tohle vyřešit

ikona D1ce:

Myslím, že i problém duplicit pro vyhledávače by šel ošetřit, tak aby byla zachována funkčnost komentovaného řešení. Akotát by to chtělo pár(teď si nejsem jistý kolik opravdu) kontrolních dotazů, dle nichž by se eventuelně přesměrovalo na správný obsah. Mohlo by vadit vyšší zatížení.

Jinak IMHO pokud na to nebudu myslet(resp. vybodnu se na to), tak v běžných aplikacích a v obvyklých intervalech změny dat, uživatele moc neošidím. :)

ikona tiso:

Ďalší problém je v tom že odkazy typu predchádzajúci/nasledujúci nie sú moc popisné, je lepšie ak sa uvedie kam daný odkaz presne vedie (napr. <a>ďalší článok: Odkaz na ďalší záznam</a>) - a to bez znalosti čo je predchádzajúci a čo nasledujúci článok nespravíš.

legoxx:

ja to pouzivam na prechadzanie obrazkov v galerii kde chybajuca popisnost az tak velmi nevadi, a potom este na prechadzanie zoradenych zoznamov v nejakom poradi a vtedy tiez popisnost nechyba.

nasledujuca funkcia vrati nasledujuce ID v pripade ak nasledujuce neexistuje tak aktualne

<?php
function get_next() {
  $stmt=$this->db->prepare("select id from pictures where date<:time|int and id>=:id|int order by date asc limit 2");
  $stmt->execute(array(":id"=>$this->id,":time"=>time()));
  $tmp=$stmt->fetchall();
  return isset($tmp[1]["id"])?$tmp[1]["id"]:$tmp[0]["id"];
}
?>

ikona Jakub Vrána OpenID:

Zapomněl jsi napsat, že to platí jen v případě, že se vzrůstajícím ID vzrůstá i datum. Za takové podmínky by se to ale dalo napsat i jednodušeji.

Např. tato data příklad dokonale rozhodí:

ID=1, date=3
ID=2, date=2
ID=3, date=1

Pro ID=1 se vrátí 2, i když další záznam už neexistuje, pro ID=2 se vrátí 2, i když další záznam ještě existuje, stejně jako pro 3 (i když z jiného důvodu).

Navíc nechápu, k čemu je vracení aktuálního záznamu, když už další neexistuje.

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.