Pozdrawiam Lucek
--
Wysłano z serwisu OnetNiusy: http://niusy.onet.pl
2) jeśli chcesz np. otrzymać na podstawie poprzedniego zapytania rekordy
np. od 21 do 30 (dokładnie 10 szt.) to trzeba na końcu dopisać:
select * from tabela order by nazwa_kolumny_sortowanej limit 20,10;
Oznacza to mniej więcej to, że ma pominąć 20 szt. z początku, a
następnie wyświetlić 10 następnych (tutaj: od 21 do 30)
i tak dalej:
select * from tabela order by nazwa_kolumny_sortowanej limit 0,10;
wyświetli rekordy od 1 do 10 (pominie ZERO)
select * from tabela order by nazwa_kolumny_sortowanej limit 120,10;
wyświetli rekordy od 121 do 130
Czy o to chodziło?
pozdrawiam
Artur
Dzieki za odpowiedz.
Widziałem to rozwiązanie jednak rozwazam je w kontekscie sortowania
globalnego czyli wszystkich rekordów w bazie.Podany kod posortuje
te 10 wierszy(dobrze rozumuje?)a nie o tym mysle.
Przedstawie to na przykladzie np prosta gra ktora posiada unikalne id
ze skojarzonym wynikiem w pewnej grze internetowej
id score
1 222
.
2 233
55 23
.
355 3235
Teraz ktos posiada tabele w ktorej moze ogladnac 10 wynikow naraz
Pobiera wyniki od 20 do 30. Szuka po id gry. Po chwili chce dostac
posortowane wyniki ale nie ta porcje 10 tylko globalnie cala tabele czyli
kto ma najwiecej punktow .Ja to widze tak - trzeba posortowac cala tabel
w jednym zapytaniu i dostane wszystkie wiersze w dobrej kolejnosci , potem
zeby nie wykonywac kolejnego zapytania zachowam to w pamieci przez pewien okres
czasu i klient bedzie mogl odpytywac tak posortowane dane.Jest to jednak
bardzo pamieciozerne i nieefektywne zatem zle zaprojektowlem.Jak to powinno
wygladac ?? Ten przyklad to nie to co robie , bede mial rowniez porownanie
ciagu znakow zatem posortowanie tego bedzie trwac znacznie dluzej.
Moje pytanie wiec brzmi jak sie mam do tego porzadnie zabrac ???
Bardzo prosze o podpowiedz
Pozdrawiam Luccek
>> Niestety nie jestem expertem i nie jestem pewien, czy zrozumiałem Twoje
>> pytanie, ale:
>> 1) jeśli chcesz posortować wyniki otrzymywane z bazy to np.:
>> select * from tabela order by nazwa_kolumny_sortowanej;
>> Zwróci wtedy posortowane wiersze wg podanej nazwy kolumny.
>>
>> 2) jeśli chcesz np. otrzymać na podstawie poprzedniego zapytania rekordy
>> np. od 21 do 30 (dokładnie 10 szt.) to trzeba na końcu dopisać:
>> select * from tabela order by nazwa_kolumny_sortowanej limit 20,10;
>>
>> Oznacza to mniej więcej to, że ma pominąć 20 szt. z początku, a
>> następnie wyświetlić 10 następnych (tutaj: od 21 do 30)
>> i tak dalej:
>> select * from tabela order by nazwa_kolumny_sortowanej limit 0,10;
>> wyświetli rekordy od 1 do 10 (pominie ZERO)
>>
>> select * from tabela order by nazwa_kolumny_sortowanej limit 120,10;
>> wyświetli rekordy od 121 do 130
>>
>> Czy o to chodziło?
> Dzieki za odpowiedz.
> Widziałem to rozwiązanie jednak rozwazam je w kontekscie sortowania
> globalnego czyli wszystkich rekordów w bazie.Podany kod posortuje
> te 10 wierszy(dobrze rozumuje?)a nie o tym mysle.
Źle rozumujesz.
> Przedstawie to na przykladzie np prosta gra ktora posiada unikalne id
> ze skojarzonym wynikiem w pewnej grze internetowej
>
> id score
> 1 222
> .
> 2 233
>
> 55 23
> .
> 355 3235
> Teraz ktos posiada tabele w ktorej moze ogladnac 10 wynikow naraz
> Pobiera wyniki od 20 do 30. Szuka po id gry. Po chwili chce dostac
> posortowane wyniki ale nie ta porcje 10 tylko globalnie cala tabele czyli
> kto ma najwiecej punktow .
Tak właśnie się stanie po zapytaniu, które przytoczył Ci poprzednik.
>Ja to widze tak - trzeba posortowac cala tabel
> w jednym zapytaniu i dostane wszystkie wiersze w dobrej kolejnosci, potem
> zeby nie wykonywac kolejnego zapytania zachowam to w pamieci przez pewien okres
> czasu i klient bedzie mogl odpytywac tak posortowane dane.Jest to jednak
> bardzo pamieciozerne i nieefektywne zatem zle zaprojektowlem.
Nigdy nie wyciągaj wszystkich rekordów. W 99% jest to błąd.
> Jak to powinno
> wygladac ?? Ten przyklad to nie to co robie , bede mial rowniez porownanie
> ciagu znakow zatem posortowanie tego bedzie trwac znacznie dluzej.
> Moje pytanie wiec brzmi jak sie mam do tego porzadnie zabrac ???
> Bardzo prosze o podpowiedz
Bazy danych zostały zaprojektowane do takiego przetwarzania, by było one
jak najbardziej optymalne i szybkie. Po prostu dobrze dobierz zapytanie tak
by baza zwróciła taką ilość danych jaką chcesz w danym momencie wyświetlić.
Przetwarzanie tych danych dopiero po wyciągnięciu z bazy jest często gęsto
nieporozumieniem i jest wolniejsze.
pozdr,
fEnIo
--
,''`. Bartosz Fenski | mailto:fe...@debian.org | pgp:0x13fefc40 | irc:fEnIo
: :' : 32-050 Skawina - Glowackiego 3/15 - malopolskie v. - Poland
`. `' phone:+48602383548 | proud Debian maintainer and user
`- http://skawina.eu.org | jid:fe...@jabber.org | rlu:172001
Powiem szczerze iz nie spodziewalem się tego W takim razie ogromny ukłon w
strone autorów tych rozwiazan i Was za odpowiedzi na moje pytanie.Dzieki
Pozdrawiam Lucek
--
Witam,
Dołączę się do wątku bo mam podobny problem.
Chcę sortować po LAST_NAME, FIRST_NAME i dla unikalności ID.
Dla samego LAST_NAME, FIRST_NAME worzyłem zapytania w stylu
WHERE (LAST_NAME>X OR (LAST_NAME=X AND FIRST_NAME>Y)
oczywiscie po dodaniu ID to się odpowiednio rozbuduje.
Niestety Postgres 'głupiał' i nie wykorzystywał indeksu, dlatego utworzyłem
indeks na LAST_NAME||' '||FIRST_NAME i uniknąłem OR w klauzuli WHERE.
Niestety po dodaniu "ID" dla uzyskania unikalności zapytania problem znów
wrócił. Nie chcę tworzyć indeksów na LAST_NAME||' '||FIRST_NAME||' '||ID bo
uważam takie konstrukcje za koszmarne, poza tym wiążę w ten sposób
uporządkowania z indeksami, chciałbym w związku z tym przekonstruować
zapytanie.
Konstrukcja LIMIT OFFSET niestety nie wygląda na wydajną dla większych
zbiorów:
EXPLAIN
SELECT "LAST_NAME","FIRST_NAME" FROM CONTACT
WHERE "COMPANY_ID" = 48
ORDER BY "LAST_NAME"||' '||"FIRST_NAME"
LIMIT 20 OFFSET 30000;
----------------------
Limit (cost=19899.24..19899.29 rows=20 width=20)
-> Sort (cost=19824.24..19907.55 rows=33327 width=20)
Sort Key: ((("LAST_NAME")::text || ' '::text) ||
("FIRST_NAME")::text)
-> Bitmap Heap Scan on contact (cost=209.64..16846.87 rows=33327
widt
h=20)
Recheck Cond: ("COMPANY_ID" = 48)
-> Bitmap Index Scan on contact_index_company
(cost=0.00..209.6
4 rows=33327 width=0)
Index Cond: ("COMPANY_ID" = 48)
(7 rows)
W porównaniu z:
EXPLAIN
SELECT "LAST_NAME","FIRST_NAME" FROM CONTACT
WHERE "COMPANY_ID" = 48
ORDER BY "LAST_NAME"||' '||"FIRST_NAME"
LIMIT 20;
----------------------------
Limit (cost=0.00..75.27 rows=20 width=20)
-> Index Scan using company_index_company_lfname on contact
(cost=0.00..125
431.28 rows=33327 width=20)
Index Cond: ("COMPANY_ID" = 48)
(3 rows)
Dla nieunikalnego uporządkowania rozwiązanie jest proste:
warunek WHERE "LAST_NAME"||' '||"FIRST_NAME">'X Y', ale po dodaniu do ORDER
BY kolumny ID wszystko się wywala...
Będę bardzo wdzięczny jeśli ktoś zaproponuje jakąś konstrukcję która nie
korzysta z OFFSET i umożliwia Postgresowi wykorzystanie indeksu na częśc
uporządkowania
Pozdrawiam,
Łukasz