sentencia postgres hacer ejemplo como asc sql postgresql sql-order-by sql-in

sql - postgres - PEDIDO POR la lista de valores IN



select postgres where (16)

Al investigar esto un poco más encontré esta solución:

SELECT * FROM "comments" WHERE ("comments"."id" IN (1,3,2,4)) ORDER BY CASE "comments"."id" WHEN 1 THEN 1 WHEN 3 THEN 2 WHEN 2 THEN 3 WHEN 4 THEN 4 END

Sin embargo, esto parece bastante detallado y puede tener problemas de rendimiento con grandes conjuntos de datos. ¿Alguien puede comentar sobre estos problemas?

Tengo una consulta SQL simple en PostgreSQL 8.3 que capta un montón de comentarios. Proporciono una lista ordenada de valores para la construcción IN en la cláusula WHERE :

SELECT * FROM comments WHERE (comments.id IN (1,3,2,4));

Esto devuelve comentarios en un orden arbitrario que en mi caso son identificadores como 1,2,3,4 .

Quiero que las filas resultantes se (1,3,2,4) como la lista en la construcción IN : (1,3,2,4) .
¿Cómo lograr eso?


Con Postgres 9.4 esto puede hacerse un poco más corto:

select c.* from comments c join ( select * from unnest(array[43,47,42]) with ordinality ) as x (id, ordering) on c.id = x.id order by x.ordering

Eliminando la necesidad de asignar / mantener manualmente una posición para cada valor.

Con Postgres 9.6 esto puede hacerse usando array_position() :

with x (id_list) as ( values (array[42,48,43]) ) select c.* from comments c, x where id = any (x.id_list) order by array_position(x.id_list, c.id);

El CTE se usa para que la lista de valores solo deba especificarse una vez. Si eso no es importante, esto también se puede escribir como:

select c.* from comments c where id in (42,48,43) order by array_position(array[42,48,43], c.id);


Creo que de esta manera es mejor:

SELECT * FROM "comments" WHERE ("comments"."id" IN (1,3,2,4)) ORDER BY id=1 DESC, id=3 DESC, id=2 DESC, id=4 DESC


El hecho de que sea tan difícil de encontrar y tenga que difundirse: en mySQL esto se puede hacer mucho más simple , pero no sé si funciona en otro SQL.

SELECT * FROM `comments` WHERE `comments`.`id` IN (''12'',''5'',''3'',''17'') ORDER BY FIELD(`comments`.`id`,''12'',''5'',''3'',''17'')


En Postgres 9.4 o posterior, esto es probablemente el más simple y rápido :

SELECT c.* FROM comments c JOIN unnest(''{1,3,2,4}''::int[]) WITH ORDINALITY t(id, ord) USING (id) ORDER BY t.ord;

  • Usando el nuevo WITH ORDINALITY , ese @a_horse ya mencionado .

  • No necesitamos una subconsulta, podemos utilizar la función de devolución de conjuntos como una tabla.

  • Un string literal para entregar en la matriz en lugar de un constructor ARRAY puede ser más fácil de implementar con algunos clientes.

Explicación detallada:


En Postgresql:

select * from comments where id in (1,3,2,4) order by position(id::text in ''1,3,2,4'')


Estoy de acuerdo con todos los demás carteles que dicen "no hagas eso" o "SQL no es bueno para eso". Si desea ordenar por alguna faceta de comentarios, agregue otra columna entera a una de sus tablas para mantener sus criterios de clasificación y ordenar por ese valor. por ejemplo, "ORDER BY comments.sort DESC" Si desea ordenar estos en un orden diferente cada vez, entonces ... SQL no será para usted en este caso.


Ligera mejora sobre la versión que usa una secuencia, creo:

CREATE OR REPLACE FUNCTION in_sort(anyarray, out id anyelement, out ordinal int) LANGUAGE SQL AS $$ SELECT $1[i], i FROM generate_series(array_lower($1,1),array_upper($1,1)) i; $$; SELECT * FROM comments c INNER JOIN (SELECT * FROM in_sort(ARRAY[1,3,2,4])) AS in_sort USING (id) ORDER BY in_sort.ordinal;


Otra forma de hacerlo en Postgres sería usar la función idx .

SELECT * FROM comments ORDER BY idx(array[1,3,2,4], comments.id)

No olvide crear primero la función idx , como se describe aquí: http://wiki.postgresql.org/wiki/Array_Index


Para hacer esto, creo que probablemente debería tener una tabla adicional "ORDEN" que defina el mapeo de los ID a ordenar (haciendo efectivamente lo que dice su respuesta a su propia pregunta), que luego puede usar como una columna adicional en su selección, que luego puedes ordenar

De esa manera, describe explícitamente el orden que desea en la base de datos, donde debería estar.


Puedes hacerlo bastante fácilmente con (introducido en PostgreSQL 8.2) VALUES (), ().

La sintaxis será así:

select c.* from comments c join ( values (1,1), (3,2), (2,3), (4,4) ) as x (id, ordering) on c.id = x.id order by x.ordering


Y aquí hay otra solución que funciona y usa una tabla constante ( http://www.postgresql.org/docs/8.3/interactive/sql-values.html ):

SELECT * FROM comments AS c, (VALUES (1,1),(3,2),(2,3),(4,4) ) AS t (ord_id,ord) WHERE (c.id IN (1,3,2,4)) AND (c.id = t.ord_id) ORDER BY ord

Pero nuevamente, no estoy seguro de que esto esté funcionando.

Tengo un montón de respuestas ahora. ¿Puedo obtener votos y comentarios para saber cuál es el ganador?

Gracias a todos :-)


sans SEQUENCE, solo funciona en 8.4:

select * from comments c join ( select id, row_number() over() as id_sorter from (select unnest(ARRAY[1,3,2,4]) as id) as y ) x on x.id = c.id order by x.id_sorter


SELECT * FROM "comments" JOIN ( SELECT 1 as "id",1 as "order" UNION ALL SELECT 3,2 UNION ALL SELECT 2,3 UNION ALL SELECT 4,4 ) j ON "comments"."id" = j."id" ORDER BY j.ORDER

o si prefieres el mal sobre el bien:

SELECT * FROM "comments" WHERE ("comments"."id" IN (1,3,2,4)) ORDER BY POSITION('',''+"comments"."id"+'','' IN '',1,3,2,4,'')


create sequence serial start 1; select * from comments c join (select unnest(ARRAY[1,3,2,4]) as id, nextval(''serial'') as id_sorter) x on x.id = c.id order by x.id_sorter; drop sequence serial;

[EDITAR]

Unnest aún no está incorporado en 8.3, pero puede crear uno usted mismo (la belleza de cualquier *):

create function unnest(anyarray) returns setof anyelement language sql as $$ select $1[i] from generate_series(array_lower($1,1),array_upper($1,1)) i; $$;

esa función puede funcionar en cualquier tipo:

select unnest(array[''John'',''Paul'',''George'',''Ringo'']) as beatle select unnest(array[1,3,2,4]) as id


select * from comments where comments.id in (select unnest(ids) from bbs where id=19795) order by array_position((select ids from bbs where id=19795),comments.id)

aquí, [bbs] es la tabla principal que tiene un campo llamado ids, y, ids es la matriz que almacena los comentarios.id.

pasado en postgresql 9.6