Mysql pořadí řádku v dotazu

Často se Vám může hodit údaj o pořadí řádku ve výsledku dotazu, např. pro různé statistiky a pořadníky soutěží, výsledkové listiny apod., ale hodit se bude i pro jiné úkoly jako zjištění dalšího záznamu, aniž bychom museli procházet tisíce záznamů v aplikační vrstvě.


Mysql a uživatelské proměnné

Poslouží nám k tomu uživatelské proměnné v mysql. Tady je jednoduchý příklad jak vypsat seznam řádků včetně jejich pořadí v dotazu.

  1. SET @poradi:=0;
  2. SELECT @poradi:=@poradi+1, @poradi as poradi, id, name FROM table ORDER BY `name` DESC;

Výhodou je použití různých podmínek pomocí specifikace WHERE, GROUP BY atd., v takových případech je tato funkce nedocenitelná.

Jak zjistit kolikátý řádek vyhovuje podmínce?

Snadné, ale dalo mi to zabrat, než jsem se k tomu dobral :-). K čemu je to dobré? No tak si vezměte příklad: Představte si, že máme stránku detailu hráče na serveru o sportovních výsledcích a chceme zjistit, kolikátý je v pořadí na počty střel, asistencí, v počtu milenek apod.

  1. SET @poradi:=0,@poradib:=0;
  2. SELECT @poradi:=@poradi+1, @poradi as poradi, IF(id=201, @poradib:=@poradi, 0), id, name FROM table ORDER BY `name` DESC;
  3. SELECT @poradib;

Výsledkem je číslo označující pořadí. Samozřejmě si můžeme zvolit řadu podmínek, např. jen hráči české národnosti apod. Když provádíte takových porovnání 10 na jedné stránce, tak není jiné východisko, určitě je to vhodnější než provádět takové porovnání na aplikační vrstvě.

Co třeba přechod na předchozí a další článek?

Pokud nejsou identifikátory souvislé a jsou mezi nimi mezery (1,2,5,6 atd.), nebo se na ně nemůžeme spolehnout, bude se nám hodit zjistit identifikátor následující po určitém záznamu nebo identifikátor záznamu předcházejícího.

  1. SET @poradi:=0,@poradinow:=0, @idnext:=0, @idprev:=0;
  2. SELECT @poradi:=@poradi+1, IF(id=201, @poradinow:=@poradi, 0) FROM table ORDER BY `name` DESC;
  3. SET @poradi:=0;
  4. SELECT @poradi:=@poradi+1, IF(@poradinow-1=@poradi, @idprev:=id, 0), IF(@poradinow+1=@poradi, @idnext:=id, 0) FROM table ORDER BY `name` DESC;
  5. SELECT @poradinow, @idnext, @idprev;

Výsledkem je vrácení pořadí záznamu s ID číslem 201 a jeho předcházející a další prvek. Osobně tento dotaz provádím až ve chvíli, kdy ho opravdu potřebuji. Tedy odkazy na předchozí a nadcházející článek aktivují funkci vyhledání pořadí a zjištění okolních článků, pak se teprve přesměruje na správnou stránku.

Samozřejmě kvůli SEO by bylo vhodné odkazy uzavřít do formuláře nebo odkaz opatřit atributem rel="nofollow", aby další články nebyly indexovány pod url http://www.stranky.cz/nejaky-clanek/next, nebo aby nedocházelo k duplicitám, kde vyhledávače pak článek vidí pod dalšími třemi adresami.

podobné články

06.04.2008Mysql pořadí řádku v dotazu, druhý díl, problém pořadí zpracování uživatelských proměnných(100%)

komentáře

RSS Komentáře k článku RSS Komentáře   Add to Google
16.04.2008 07:37 | Anonym (v6ak) | 

Já bych opatřil noindex hlavě tu stránku next. BTW: není pro vyhledávače nejlepší, když mají Předchozí článek Mysql poředí řádků v dotazu? Stejně to IMHO nezabere moc času.

17.04.2008 12:25 | Administrátor | Re: Anonym (v6ak)

Problém je hlavně v tom, že abych znal název předchozího a příštího článku musel bych provést ten dotaz už při výpisu aktuálního článku. Snažím se šetřit nároky na železo tím, že se dotaz provádí až, když je potřeba. Nemyslím, že je tento dotaz příliš složitý, ale v dalším díle už je to něco jiného.

01.06.2008 17:25 | Anonym (Kcko) | Jak zjistit kolikátý řádek vyhovuje podmínce?

Mel bych jeste jeden figl ktery by mohl byt rychlejsi..

Zjoinovat tabulku se sama sebou a a do WHERE dat podminky a do SELECTU COUNT(*) + 1 a dostaneme to same, rychlostne mozna lepsi … akorat Spojojovani tabulky se sama sebou dost casto lidi nechapu

02.06.2008 12:43 | Administrátor | Re: Jak zjistit kolikátý řádek vyhovuje podmínce?

další díl tohoto problému je trochu složitější, co když dotaz má 10 joinů, zkus někde popsat ten fígl a dej sem odkaz, nebo ho napiš já ti ho tady zveřejním

02.06.2008 16:47 | Anonym (Kcko) | Oky

Oky snad neco sesmolim az nebudu mit frmol ve worku [http://www.rjwebdesign.net/Blog]

Jinak pochvala, zajimave ctivo ( obzvlast sekce MYSQL )

Jinak by me zajimalo jak to bude s rychlosti

1. SET @poradi:=0,@po­radib:=0;
2. SELECT @poradi:=@poradi+1, @poradi as poradi, IF(id=201, @poradib:=@poradi, 0), id, name FROM table ORDER BY name DESC;
3. SELECT @poradib;

Porad to jsou 3 dotazy, kdyz budu mit na strance treba 5 tabulek ⇒ 15 dotazu , jak to bude rychle?

Predpokladam ze dotaz na nastaveni poradi bude pro server zanedbatelny nebo se pletu?

03.06.2008 18:16 | Administrátor | Re: Oky

určitě zanedbatelný, první je nastavení uživatelské proměnné (nemá vliv na rychlost), poslední je vypsání obsahu uživatelské proměnné (nemá vliv na rychlost)

předpokládám, že na jedné stránce nebude 5× stránkování nebo prostě výpis 5× nějakého seznamu, kde by byl vhodný přechod na další záznam nebo ano? pokud ano určitě bych to rozdělil na více stránek

03.06.2008 18:24 | Anonym (Kcko) | Re: Re: Oky

Jasne, ja si akorat rikam ze musi projet vsechny radky v DB ( resp podle SQL dotazu ) aby je ocisloval a ja na mem hernim portalu [http://www.pesonline.cz] pouzivam ruzne praktiky, nekde je rychle to jinde zase ono.

( Kesovani SQL dotazu, ocislovani radku po updatu natvrdo atd ..)

Uvital bych RSS a vice clanku z MYSQL :) , napriklad na tuto tematiku [http://www.rjwebdesign.net/…love-Tabulky]

04.06.2008 23:05 | Administrátor | Re: Re: Re: Oky

očíslování řádku bohužel nelze použít na různé filtry, výhodou tohoto je možnost použít i přeskakování na další a předchozí články dle parametrů vyhledávání! běžně to používám v systémech, kde je až 20 parametrů vyhledávání a více než 100 000 položek, zatím to jede svižně :), každopádně třeba uvedu příklad, kde si to jinak nedokážu představit: články jsou filtrovány podle kategorie, osoby která vložila články, a textu který obsahují, přesto výsledek tvoří např. 1000 článků, a nyní potřebujeme jejich překlady, tlumočník, jen píše překlad a kliká na další článek, žádné zdržování s přecházením na seznam článků apod.,

RSS – je ve spodu stránky, jestli myslíš RSS diskusí, tak ano brzy bude, stejně tak odesílání nových příspěvků na mail

jinak co se týče odkazu zkus formulovat více svůj zájem, jsem autorem www.nhlpro.cz z této problematiky mám několikaleté zkušenosti, v rámci časových možností by mohlo něco více přibývat :)

05.06.2008 14:20 | Anonym (Kcko) | Re: Re: Re: Re: Oky

Heh, tak to jsme se spolu uz asi bavili, s nekym z NHLPRO jsem se bavil a ted nevim kdo to byl :) // cca 3–6 mesicu zpet /

Zrovna se mi libilo http://www.nhlpro.cz/hraci/hrac.php?…

ze v teto osobni karte hrace vidim kolikaty v zebricku je treba v golech , nahravkach atd .. ale to asi resi toto ze? –

Jinak by me z nhlpro.cz zajimala asi tak 1/3 vsech skriptu .. :) napriklad jakym stylem se generuji tabulky

http://www.nhlpro.cz/tymy/poradi.php?…

http://www.nhlpro.cz/tymy/poradi.php?…

Co vsechno se tam kesuje, jakym stylem. Urcite i teoreticke uvahy o tom jak ukladat data i reduntantne aby se potom tolik nezatezovala databaze …

Sry za rozepsani, vidim spriznenou dusi ( statistiky, tabulky a to je moje viz jiz jednou zminovany )

No budu se tesit :)

06.06.2008 01:13 | Administrátor | Re: Re: Re: Re: Re: Oky

no co se tyce nhlpro, je tam 10k navstev denne v sezone, ale zklamu tě, přesto že mám plán co kešovat a jak postupovat s projektem dále, jsem jen programátor, o těchto věcech rozhoduje manažer, v sezóně jsme měli hodně problémy, co se týče návštěvnosti, byla tak vysoká, že to server nedokázal obsloužit a díky tomu zbytečně server přicházel o návštěvnost, v současné době už dlouhodobě jednáme o možných změnách, takže nebudu prozrazovat více ze zákulisí, každopádně když položíš konkrétní dotazy jsem ochoten zpracovat v rámci možností článek s odpověďmi

06.06.2008 10:34 | Anonym (Kcko) | Re: Re: Re: Re: Re: Re: Oky

To je v poradku, mam taky svoji kesovaci tridu a ze je velmi dobra :) ( kesovani SQL do pameti ..)

Me by spis tedy nez kesovani zajimalo to co jsem napsal v predchozim komentari.

Tesil bych se ne nejaky mensi serial clanku o tom jak pocitat sportovni tabulky a statistiky obecne ( nemusi to byt dopodrobna ) , tak aby nebyl problem se zatezi ani pracnosti.

Tabulky, statistiky … atd Mam te v RSS tak se budu tesit.

06.06.2008 14:33 | Administrátor | Re: Re: Re: Re: Re: Re: Re: Oky

Co takhle si napsat kokrétní věci co by tě zajímali, nevím jestli by takový seriál krom tebe někoho zajímal?

Třeba nadpisy článků a tak? Zajímá tě programování nebo počítání statistik? Krom toho si myslím, že půjde o hokej jiné sporty jiné výpočty.

06.06.2008 15:06 | Anonym (Kcko) | Re: Re: Re: Re: Re: Re: Re: Re: Oky

Mno ono vseobecne moc lidi toto nezajima, nebo tedy nevim o nikom kdo by se tolik vyzival ve statistikach a tabulkach ve sportu.

Napsat konkretni veci samozrejme muzu, ale ma cenu si takhle psat do komentaru? Co treba nekdy na ICQ, treba bych Ti predal i ja cosi.

Jinak nechapu, nadpisy clanku ?

>> Zajímá tě programování nebo počítání statistik?

Programovani ani tolik snad ne, kazdy ma vlastni styl psani kodu atd ale spis ten zpusob jak to rozdelit / cili vykon a umisteni dat aby to bylo v dobrem pomeru a dalo se z toho vse vytahnout .. /

Jestli se Ti do toho nechce np, nejsem zvykly otravovat

Kontakt na Tebe nemam, muj je na www.rjwebdesign.net/Kontakt

Pekny vikend

11.06.2008 12:42 | Anonym (Kajman) | nesmyslě složitě

Na pořadí přeci stačí sečíst počet řádků, které po seřazení budou nahoře nad akutálním a přičíst jedničku. Takže jen obyčejné where.

Na další stačí obdobně vybrat jen např. nejmenší z větších… select id dalsi from tabulka where id>201 order by id limit 1

12.06.2008 12:30 | Administrátor | Re: nesmyslě složitě

napiš prosím, tedy ten jednoduchý dotaz s tímto zadáním:

Kolikátý je hráč v pořadí podle počtu vstřelených gólů?

15.06.2008 14:10 | Anonym () | Re: Re: nesmyslě složitě

$pocet_golu_hrace

select count(*)+1 poradi from tabulka t where t.golu>$pocet_go­lu_hrace

15.06.2008 14:46 | Administrátor | Re: Re: Re: nesmyslě složitě

Hm zajimavé, ale asi sis nepřečetl o čem je článek. Netuším co tohle vrátí, ale řekni mi jak z tohohle selectu zjistit kolikátý je Jágr v žebříčku počtu vstřelených branek v roce 2008?

15.06.2008 15:22 | Anonym (Kajman) | Re: Re: Re: Re: nesmyslě složitě

select count(*)+1 poradi from tabulka t where t.rok=2008 and t.golu>(select j.golu where j.rok=2008 and j.hrac=‚Jágr‘)

Prostě spočítáte, kolik je před ním… tedy má více gólů.

15.06.2008 16:10 | Administrátor | Re: Re: Re: Re: Re: nesmyslě složitě

přiznám se, že sem dlouho hledal řešení, tohle vypadá jednoduše, proto je mi divné, že bych na to nepřišel, zkusím v rámci času přes týden projít, proč jsem to neřešil takhle, dej sem odkaz na nějaký tvůj blog nebo něco pokud máš

jinak proč nesmyslně? rozhodně to funguje

15.06.2008 17:11 | Administrátor | Re: Re: Re: Re: Re: nesmyslě složitě

tak už tuším proč jsem to nepoužil:

  1. goly se v tabulce pocitaji za zapasy, takže je nutné použít sum() a taky group by IDhrace, pak by count(*) neměl smysl, protože by počítal jen výskyty toho hráče
  2. zjednodušením vznikl tento článek, každopádně mne teď nenapadá problém proč nepoužít to co píšeš, snad jen, že je nutný druhý subselect, což v mém případě není nutné
  3. otázka je co nabízí více možností, např. příští článek a předchozí článek? jak třeba pomocí metody „Kajman“ vypsat článek v pořadí 351?
  4. vařím z vody není moc čas, tak doufám, že mé závěry jsou správně, ale třeba se mýlím, každopádně proč zavrhovat mou metodu? její nevýhodu vidím v tom, že musí projít cyklem úplně všechny řádky, což by mohl být problém! ale jinak, šlo o to jak pomocí uživatelských proměnných počítat pořadí řádku a pak s ním manipulovat, Kajman metoda šikovně obchází smysl
15.06.2008 21:44 | Anonym (Kajman) | Re: Re: Re: Re: Re: Re: nesmyslě složitě

To není metoda „Kajman“, následující, další mi takhle kdysi taky někdo poradil. Je to jednoduché rychlé řešení. Mohou se vracet klidně všechny sloupečky a oba směry lze spojit přes union, takže stačí jeden jediný dotaz.

A limit 350,1 vypíše 351. řádek – žádné složitosti

16.06.2008 14:47 | Administrátor | Re: Re: Re: Re: Re: Re: Re: nesmyslě složitě

metoda kajman pracovní označení :), neřekl jsem, že je to blbost, proč ne, jsou to dva složené dotazy to při mém řešení není nutné přece?

proč hned odsuzuješ použití uživatelských proměnných?co je na tom složitého? myslíš, že je nastavení uživatelské proměnné nějak náročné?nebo dotaz na získání uživatelské proměnné?

25.06.2008 07:49 | Anonym (Kajman) | Re: Re: Re: Re: Re: Re: Re: Re: nesmyslě složitě

Myslím, že náročnost pro db by se dala otestovat dotazy nad statisícem řádků – podle mého odhadu tam bude celkem rozdíl v rychlosti.

15.06.2008 21:52 | Anonym (Kajman) | Re: Re: Re: Re: Re: Re: nesmyslě složitě

A při group by, můžete dát select count(*)+1 from (select sum(gol) golu group by hrac having golu>$goly_jagra)

01.05.2011 16:21 | Anonym (Visitor) | Proč tak složitě?

Pokud máme seznam u kterého se chceme pohybovat PREV a NEXT směrem seřazený podle čísel (klidně i v nesouvislé řadě) nebo času, tak toto je zbytečný kanón na vrabce. Je to v článku jen povrchně zmíněno a zasloužilo by to více zdůraznit, než to někdo jen bezmyšlenkovitě zkopíruje. Pokud chci další článek po článku s id=201, tak to jednoduše udělám následovně: SELECT * FROM clanky WHERE id > 201 ORDER BY id LIMIT 1

U řazení podle času to bude fungovat stejně spolehlivě. Věřím, že by to fungovalo i s textem, ale tam už by to zavánělo magií.

01.05.2011 17:24 | Administrátor | Re: Proč tak složitě?

článek je obecné řešení, vaše řešení funguje pouze v konkrétním případu, představte si nějaký obecný datagrid, kde si uživatel podmínky vyhledávání, řazení atd. nakliká sám, pak je vaše řešení nepoužitelné

Jméno
Název
Text
Lze používat Texy! syntax. Příklad syntaxe: "text odkazu":odkaz, **tučně**, *kurzíva*, `code`. PHP kód uzavírejte do <?php ... ?> a JavaScript do <script> ... </script>