Reputation: 2437
Want result in same order as passed to IN
condition:
SELECT "id",
"field_a",
"field_b",
To_timestamp("on_dated")
FROM "test"
WHERE "id" IN ( 3, 1, 6, 2, 4 );
Getting:
id | field_a | field_b | on_dated ------------------------------------- 1 | Vinay | M | 1383224064 2 | Asha | F | 1383224064 3 | Shashi | F | 1383224064 4 | Vinita | F | 1383224064 5 | Arnav | M | 1383224064 6 | Jayant | M | 1383224064
Expecting:
id | field_a | field_b | on_dated ------------------------------------- 3 | Shashi | F | 1383224064 1 | Vinay | M | 1383224064 6 | Jayant | M | 1383224064 2 | Asha | F | 1383224064 4 | Vinita | F | 1383224064
Tried:
SELECT "id",
"field_a",
"field_b",
To_timestamp("on_dated")
FROM "test"
WHERE "id" IN ( 3, 1, 6, 2, 4 )
ORDER BY Field("id", '3', '1', '6', '2', '4');
But throws error :(
Found a better answer:
Also I found a more compact answer for this:
SELECT * FROM "test"
WHERE "id" IN (3,1,6,2,4)
ORDER BY (id=3, id=1, id=6, id=2, id=4) DESC;
Upvotes: 1
Views: 113
Reputation: 659307
A set has no order by definition. So your original question cannot be answered. It only works by supplying additional information (like you do in your added solution).
You can pass an array as provided by @a_horse. I would advice to use generate_subscripts()
in this case like demonstrated here:
PostgreSQL unnest() with element number
There is a new feature in the upcoming Postgres 9.4 (in development now) that makes this a lot simpler: WITH ORDINALITY
. Details in the same answer.
For now, you can use a set of composite types including row numbers:
SELECT t.*
FROM test t
JOIN (
VALUES
(1, 3)
,(2, 1)
,(3, 6)
,(4, 2)
,(5, 5)
) val(rnk, test_id) USING (test_id)
ORDER BY val.rnk;
Upvotes: 1
Reputation:
The only way I can think of is something like this:
with numbers (id, sort_order) as (
values
(3,1),
(1,2),
(6,3),
(2,4),
(4,5)
)
SELECT t.id,
t.field_a,
t.field_b,
to_timestamp(t.on_dated)
FROM test
JOIN numbers n on t.id = n.id
ORDER BY n.sort_order;
Another slightly more compact version:
with numbers (id, sort_order) as (
select i,
row_number() over ()
from unnest(ARRAY[3,1,6,2,4]) i
)
SELECT t.id,
t.field_a,
t.field_b,
to_timestamp(t.on_dated)
FROM test
JOIN numbers n on t.id = n.id
ORDER BY n.sort_order;
But: this relies on the fact that unnest always produces the rows in the same order. I'm not entirely sure this is always the case.
If you need this functionality very often, you can create a function to do that:
create or replace function get_index(to_find integer, elements int[])
returns integer
as
$$
declare
idx integer;
x integer;
begin
idx := 1;
foreach x in array elements
loop
if to_find = x then
return idx;
end if;
idx := idx + 1;
end loop;
return -1;
end;
$$
language plpgsql;
Then you can write:
SELECT id,
field_a,
field_b,
to_timestamp(on_dated)
FROM test
WHERE id = any (array[2,7,3,1])
ORDER BY get_index(id, array[2,7,3,1]);
Upvotes: 1