Portál AbcLinuxu, 13. května 2025 00:54

Dotaz: Postgres: filtrovani na zaklade vztahu mezi jednotlivymi radky

8.4.2015 19:07 Jiri Tomasek
Postgres: filtrovani na zaklade vztahu mezi jednotlivymi radky
Přečteno: 690×
Odpovědět | Admin
Ahoj,

predstavme si, ze mame tuto sql tabulku:

identifikator skore
a 13
a 12
a 15
a 14
b 3
b 5
b 7
chci ji transformovat na tabulku, kde budou ponechany max 3 radky pro kazdy identifikator, ktere maji nejvetsi skore. Tedy aby "a 12" bylo vyfiltrovano. Jde to nejak jednoduse?

(BTW Proc to chci: potrebuji totiz prumer 3 nejvetsich skore pro kazdy identifikator. Ano, to by asi slo primo pres nejakou agregacni funkci, ale ta defaultne nejspis neexistuje. Proto zkousim tabulku nejdrive vyfiltrovat a pak je to snadne.)

Řešení dotazu:


Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

Řešení 1× (karl82)
okbob avatar 8.4.2015 19:51 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
Rozbalit Rozbalit vše Re: Postgres: filtrovani na zaklade vztahu mezi jednotlivymi radky
Odpovědět | | Sbalit | Link | Blokovat | Admin
Technik jak tento problém vyřešit je několik, jeden z nejjednodušších je použití window funkce:
postgres=> select * from t;
 x | y  
---+----
 a | 13
 a | 12
 a | 15
 a | 14
 b |  3
 b |  5
 b |  7
(7 rows)

postgres=> select x,y from (select rank() over(partition by x order by y desc), x, y from t) s where rank <= 3;
 x | y  
---+----
 a | 15
 a | 14
 a | 13
 b |  7
 b |  5
 b |  3
(6 rows)
Je to dobrá úloha na naučení se trochu netriviálního SQL (naučit se všechny varianty).
okbob avatar 8.4.2015 19:53 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
Rozbalit Rozbalit vše Re: Postgres: filtrovani na zaklade vztahu mezi jednotlivymi radky
Jinak přes agregační funkce by to vyřešit nešlo - ty agregují nikoliv filtrují.
9.4.2015 11:43 Jiri Tomasek
Rozbalit Rozbalit vše Re: Postgres: filtrovani na zaklade vztahu mezi jednotlivymi radky
Uzasny! Diky za rozsireni obzoru.

Agregacni funkce - myslel jsem napsat si vlastni, neco jako

SELECT id, PRUMER_NEJVSSICH_TRI(skore) GROUP BY id;
okbob avatar 9.4.2015 12:20 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
Rozbalit Rozbalit vše Re: Postgres: filtrovani na zaklade vztahu mezi jednotlivymi radky
agregacni funkce vraci skalarni (jednu) hodnotu - takze to z principu nejde. Ale mozna je to o terminologii - mozna jste mel na mysli window funkce :)
9.4.2015 13:01 Jiri Tomasek
Rozbalit Rozbalit vše Re: Postgres: filtrovani na zaklade vztahu mezi jednotlivymi radky
Jasne, vsak PRUMER_NEJVYSSICH_TRI() prece je skalarni hodnota :-)

Jen jsme si asi nerozumeli, ta agregacni funkce by vyresila trochu jiny problem nez filtrovani - viz text za BTW v puvodni otazce.
okbob avatar 9.4.2015 17:59 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
Rozbalit Rozbalit vše Re: Postgres: filtrovani na zaklade vztahu mezi jednotlivymi radky
Aha, to jsem si neprecetl pozorne otazku. Pak by to slo.
17.4.2015 14:17 rich
Rozbalit Rozbalit vše Re: Postgres: filtrovani na zaklade vztahu mezi jednotlivymi radky
agregaci muzes pouzit primo v dotazu... netreba vytaret dalsi funkce
4.5.2015 18:51 Chobotnice
Rozbalit Rozbalit vše Re: Postgres: filtrovani na zaklade vztahu mezi jednotlivymi radky
Pokud se to skore ma opakovat, chces asi spis dense rank nez rank.
Josef Kufner avatar 20.4.2015 15:49 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: Postgres: filtrovani na zaklade vztahu mezi jednotlivymi radky
Odpovědět | | Sbalit | Link | Blokovat | Admin
Dá se to naprasit pomocí několika subselectů:
SELECT t1.id, (
  SELECT AVG(t2.skore)
  FROM (
    SELECT t3.skore
    FROM t AS t3
    WHERE t3.id = t1.id
    ORDER BY t3.skore DESC
    LIMIT 3
  ) AS t2
) AS prumer_3_nejvyssich
FROM t as t1
GROUP BY t1.id
ORDER BY t1.id
Hello world ! Segmentation fault (core dumped)
21.4.2015 09:49 Jiri Tomasek
Rozbalit Rozbalit vše Re: Postgres: filtrovani na zaklade vztahu mezi jednotlivymi radky
No vida, to je taky hezky reseni :)

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.