Autor Zpráva
CZechBoY
Profil
Zdravím,
nějaký tip jak limitovat počet vrácených řádků pro každou skupinu v MySQL? V oraclu už to mám.
Mám dotaz, který vrátí všechny záznamy (bez limitace řádků):
SELECT DISTINCT id, child_id FROM table WHERE id IN (1,2,3,4,5,6,7)
Potom jsem zkoušel nějakej sql podle SO (s limitací na 3 řádky):
SET @rank := 0;
SET @curr := '';

SELECT * 
FROM ( 
    SELECT DISTINCT child_id, id, @rank := IF(@curr = id, @rank+1, 1) rank, @curr := id
    FROM table
    WHERE id IN (1,2,3,4,5,6,7)
    ORDER BY id, child_id
) ranked 
WHERE ranked.rank <= 3

Díky za rady.
Taps
Profil
CZechBoY:
Některé časteji řešené dotazy pro MySQL - FAQ » Nalezení posledních pěti článků z každé kategorie
User
Profil *
LIMIT 3
CZechBoY
Profil
Taps [#2]:
zkusim

User [#3]:
to mám dát kam?
Lonanek
Profil
CZechBoY:
to mám dát kam?
Uvedeno v odkazu od Taps, nebo zde.
CZechBoY
Profil
No ja nechci max 3 celkem, ale 3 od kazde skupiny..
CZechBoY
Profil
Taps [#2]:
Tak jsem to přepsal takto:
SELECT id, child_id
FROM table
JOIN (
  SELECT id, (
    SELECT child_id FROM table 
    WHERE id = k.id
    ORDER BY child_id ASC
    LIMIT 3,1
  ) hranice
  FROM table k
) h ON table.id = h.id and table.child_id <= ifnull(h.hranice, table.child_id)
/* WHERE id = 1 */
A strašně dlouho to trvá na pár (vyhledávání 3 řádků v 1000 pro jednu skupinu, kterou mám ve where jako jedinou) řádcích :(
Pokud to zkusim na nějaký menší skupině tak to vyhodí všechny řádky bez limitu 3 :(
juriad
Profil
CZechBoY:
Jaké máš indexy na tabulce? Jaký je explain dotazu?
Aha, ty máš obecný strom a nikoli dvě tabulky kategorí a článků. Ten vnitřní dotaz na 4. řádku totiž počítá pořád to samé.
juriad
Profil
Pro manuální propagaci podmínky na id přidej WHERE podmínky do obou dotazů, jak je naznačeno.
SELECT id, child_id
FROM table
JOIN (
  SELECT id, (
    SELECT child_id FROM table 
    WHERE id = k.id
    ORDER BY child_id ASC
    LIMIT 2,1 # přeskoč dva a vrať jeden
  ) hranice
  FROM (
    SELECT DISTINCT id
    FROM table
    # WHERE id = 1
  ) k
) h ON table.id = h.id and table.child_id <= ifnull(h.hranice, table.child_id)
# WHERE id = 1
CZechBoY
Profil
juriad [#8]:
To je jen zjednodušený příklad :-)
Mám dvě tabulky, který potřebuji spojit - z jedné vybírám child_id a z druhé id, podle kterého filtruje; joinuje se ještě podle jiného sloupce.
neboli v pseudokodu
SELECT id, child_id FROM tbl1 JOIN tbl2 USING (join_id) WHERE id IN (10,20,15,1,99)

minimální struktura cca
tbl1
- child_id (int)
- join_id (int)

tbl2
- id (int)
- join_id (int)

indexy:
tbl1
- nějaký idečko (vůbec se nepoužívá)
- child_id
- join_id

tbl2
- PK: id, join_id
- join_id
- id
Kajman
Profil
To nehraje roli. Hlavní je mít v tom poddotaze "k" jen tolik řádků, kolik skupin budete mít. V FAQ to byl číselník kategoriií, pokud číselník nemáte, tak si seznam skupin můžete generovat tím distinc dotazem.
CZechBoY
Profil
Kajman [#11]:
díky za odpověď. tak jsem to zkusil a vykouzlil
SELECT c1.id, child_id FROM seda s1 JOIN cerna c1 USING (join_id)
JOIN (
  SELECT id, (
    SELECT child_id FROM seda s3
    WHERE join_id = k.join_id
    ORDER BY child_id ASC
    LIMIT 2,1
  ) hranice
  FROM (
    SELECT DISTINCT id, join_id FROM cerna c2
    # WHERE id = 1
  ) k
) h ON c1.id = h.id AND s1.child_id <= IFNULL(h.hranice, s1.child_id)
# WHERE id = 1

Ale furt mi to háže všechny řádky :-(
Kajman
Profil
V tom poddotaze "h" máte distinct na kombinaci dvou sloupců. Dejte tam jen jeden sloupec - ten podle kterého chcete seskupovat.

Když si samostatně pustíte ten dotaz ze závorky "h", musí vrátit jen neopakující se seznam skupin pro ty trojice.

Edit: a ten dotaz z [#1] možná blbne díky distinct, kdyby se to volalo jako
select promenne from (select distinct bez promennych)
tak by to asi fungovalo.
CZechBoY
Profil
Kajman [#13]:
Tak potom už to jede, sice to nevrátí stejnej výsledek jako bych očekával když dám jednoduchý select
SELECT child_id FROM seda JOIN cerna USING (join_id) WHERE cerna.id = 1 ORDER BY child_id ASC LIMIT 3
ale stejně to trvá strašně dlouho :(
seda má 1.7M řádků celkem, cerna má 11k řádků celkem... jsou to relativně malý čísla (rozhodně ta druhá tabulka) a položení 30 dotazů vychází mnohem rychleji (do sekundy všechny).

Nakonec jsem zjistil v čem byla příčina v mém původním SQL dotazu s uživatelskými proměnnými - chyběl force index na cerna.id

Tímto děkuji zúčastněným, ale radši použiju tu původní variantu s proměnnými :-)

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: