Mam proste zapytanie SQL w PostgreSQL 8.3, które przechwytuje kilka komentarzy. Podaję posortowaną listę wartości do IN
konstrukcji w WHERE
klauzuli:
SELECT * FROM comments WHERE (comments.id IN (1,3,2,4));
To zwraca komentarze w dowolnej kolejności, która w moim przypadku jest podobna do identyfikatorów 1,2,3,4
.
Chcę wynikające wierszy posortowanych jak listy w IN
konstrukcie: (1,3,2,4)
.
Jak to osiągnąć?
sql
postgresql
sql-order-by
sql-in
orzechówka
źródło
źródło
Odpowiedzi:
Możesz to zrobić dość łatwo za pomocą (wprowadzonych w PostgreSQL 8.2) VALUES (), ().
Składnia będzie następująca:
źródło
with ordered_products as (select row_number() OVER (ORDER BY whatever) as reportingorder, id from comments) ... ORDER BY reportingorder
.Tylko dlatego, że jest tak trudny do znalezienia i trzeba go rozpowszechniać: w mySQL można to zrobić znacznie prościej , ale nie wiem, czy działa to w innym SQL.
źródło
ERROR: cannot pass more than 100 arguments to a function
W Postgres 9.4 lub nowszym jest to prawdopodobnie najprostsze i najszybsze :
Używając nowego
WITH ORDINALITY
, wspomnianego już @a_horse .Nie potrzebujemy podzapytania, możemy użyć funkcji zwracającej set, jak tabeli.
Literał łańcuchowy do przekazania w tablicy zamiast konstruktora ARRAY może być łatwiejszy do zaimplementowania w przypadku niektórych klientów.
Szczegółowe wyjaśnienie:
źródło
Myślę, że ten sposób jest lepszy:
źródło
... order by id=? desc, id=? desc, id=? desc
i wydaje się, że działa dobrze :-)Z Postgres 9.4 można to zrobić trochę krócej:
Lub nieco bardziej zwarty bez tabeli pochodnej:
Eliminacja konieczności ręcznego przypisywania / utrzymywania pozycji dla każdej wartości.
W Postgres 9.6 można to zrobić za pomocą
array_position()
:CTE jest używane, więc lista wartości musi być określona tylko raz. Jeśli to nie jest ważne, można to również zapisać jako:
źródło
IN
listy zWHERE
klauzuli wORDER BY
klauzuli, co sprawia, że jest to najlepsza odpowiedź imho ... Teraz tylko po to, aby znaleźć coś podobnego dla MySQL ...order by array_position(array[42,48,43], c.id::int);
co może w niektórych przypadkach prowadzić do błędów.array_position(array[42, 48, 43]::bigint[], c.id::bigint)
, więc nie ma potrzeby skracaniabigint
doint
.Innym sposobem na zrobienie tego w Postgres byłoby użycie
idx
funkcji.Nie zapomnij
idx
najpierw utworzyć funkcji, jak opisano tutaj: http://wiki.postgresql.org/wiki/Array_Indexźródło
CREATE EXTENSION intarray;
.enable_extension
pozwoli ci to aktywować, o ile użytkownik aplikacji jest członkiemrds_superuser
grupy.W Postgresql:
źródło
position(id::text in '123,345,3,678')
. Identyfikator3
będzie pasował przed identyfikatorem345
, prawda?Poszukując tego trochę więcej, znalazłem takie rozwiązanie:
Jednak wydaje się to raczej rozwlekłe i może powodować problemy z wydajnością w przypadku dużych zbiorów danych. Czy ktoś może wypowiedzieć się na temat tych kwestii?
źródło
IN
klauzula zawiera tysiące wartości ? ponieważ muszę to zrobić dla tysięcy płyt.Aby to zrobić, myślę, że prawdopodobnie powinieneś mieć dodatkową tabelę „ZAMÓWIENIE”, która definiuje mapowanie identyfikatorów do zamówienia (skutecznie robiąc to, co mówi twoja odpowiedź na własne pytanie), której możesz następnie użyć jako dodatkowej kolumny w wybranym możesz następnie posortować.
W ten sposób wyraźnie określasz pożądaną kolejność w bazie danych, gdzie powinna się znajdować.
źródło
sans SEQUENCE, działa tylko na 8.4:
źródło
lub jeśli wolisz zło od dobra:
źródło
A oto inne rozwiązanie, które działa i wykorzystuje stałą tabelę ( http://www.postgresql.org/docs/8.3/interactive/sql-values.html ):
Ale znowu nie jestem pewien, czy to działa.
Mam teraz kilka odpowiedzi. Czy mogę uzyskać głos i komentarze, żeby wiedzieć, kto wygrał!
Dziękuje wszystkim :-)
źródło
[EDYTOWAĆ]
unnest nie jest jeszcze wbudowany w 8.3, ale możesz go stworzyć samodzielnie (piękno każdego *):
ta funkcja może działać w każdym typie:
źródło
Nieznaczne ulepszenie w stosunku do wersji używającej sekwencji, jak myślę:
źródło
tutaj [bbs] jest główną tabelą zawierającą pole o nazwie ids, a ids to tablica przechowująca komentarze.id.
przekazano w postgresql 9.6
źródło
Zobaczmy, co zostało już powiedziane. Na przykład masz stół z kilkoma zadaniami:
I chcesz uporządkować listę zadań według statusu. Status to lista wartości ciągów:
Sztuczka polega na tym, aby nadać każdej wartości statusu interger i uporządkować listę numeryczną:
Który prowadzi do:
Kredyt @ user80168
źródło
Zgadzam się ze wszystkimi innymi plakatami, które mówią „nie rób tego” lub „SQL nie jest w tym dobry”. Jeśli chcesz sortować według jakiegoś aspektu komentarzy, dodaj kolejną kolumnę liczb całkowitych do jednej z tabel, aby przechowywać kryteria sortowania i sortować według tej wartości. np. "ORDER BY comments.sort DESC" Jeśli chcesz sortować je w innej kolejności za każdym razem, ... SQL w tym przypadku nie będzie dla Ciebie.
źródło