问题
Ok, there are some answers out there on how to do this. But all of the answers are assuming that the query is selecting all. If you have a distinct select, the methods no longer work.
See here for that method: Simulating MySQL's ORDER BY FIELD() in Postgresql
Basically I have
SELECT DISTINCT id
FROM items
WHERE id IN (5,2,9)
ORDER BY
CASE id
WHEN 5 THEN 1
WHEN 2 THEN 2
WHEN 9 THEN 3
END
Of course, this breaks and says
"PGError: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list"
Is there any way to order your query results in PostgreSQL by the order of the values in the IN clause?
回答1:
You can wrap it into a derived table:
SELECT *
FROM (
SELECT DISTINCT id
FROM items
WHERE id IN (5,2,9)
) t
ORDER BY
CASE id
WHEN 5 THEN 1
WHEN 2 THEN 2
WHEN 9 THEN 3
END
回答2:
From documentation:
Tip: Grouping without aggregate expressions effectively calculates the set of distinct values in a column. This can also be achieved using the DISTINCT clause (see Section 7.3.3).
SQL query:
SELECT id
FROM items
WHERE id IN (5,2,9)
GROUP BY id
ORDER BY
CASE id
WHEN 5 THEN 1
WHEN 2 THEN 2
WHEN 9 THEN 3
END;
回答3:
Looking around I couldn't find a complete solution to this question.
I think the better solution is to use this query
SELECT *
FROM items
WHERE id IN (5,2,9)
ORDER BY idx(array[5,2,9]::integer[], items.id)
If you are using PostgreSQL >= 9.2 you can enable the idx function enabling the extension.
CREATE EXTENSION intarray;
Otherwise you can create it with the following:
CREATE OR REPLACE FUNCTION idx(anyarray, anyelement)
RETURNS INT AS
$$
SELECT i FROM (
SELECT generate_series(array_lower($1,1),array_upper($1,1))
) g(i)
WHERE $1[i] = $2
LIMIT 1;
$$ LANGUAGE SQL IMMUTABLE;
I really suggest to use ::integer[]
in the query because if you are creating the array dynamically is possible that it has no elements resulting in ids(array[], items.id)
which would raise an exception on PostgreSQL.
回答4:
I create this function in postgres PL/PGSQL and it is a lot easier to use.
-- Function: uniqueseperategeomarray(geometry[], double precision)
-- DROP FUNCTION uniqueseperategeomarray(geometry[], double precision);
CREATE OR REPLACE FUNCTION manualidsort(input_id int, sort_array int[])
RETURNS int AS
$BODY$
DECLARE
input_index int;
each_item int;
index int;
BEGIN
index := 1;
FOREACH each_item IN ARRAY sort_array
LOOP
IF each_item = input_id THEN
RETURN index;
END IF;
index := index+1;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql;
ALTER FUNCTION manualidsort(int, int[])
OWNER TO staff;
And when you run a query, go like this...
SELECT * FROM my_table ORDER BY manualidsort(my_table_id, ARRAY[25, 66, 54])
来源:https://stackoverflow.com/questions/6822651/postgresql-order-by-values-in-in-clause