2011-07-25 36 views
5

好的,關於如何執行此操作,有一些答案。但所有的答案都假設查詢選擇了全部。如果你有一個獨特的選擇,這些方法不再有效。IN()子句中的PostgreSQL ORDER BY值

在這裏看到的是方法:Simulating MySQL's ORDER BY FIELD() in Postgresql

基本上我有

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 

當然,這休息,並說

"PGError: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list"

有什麼辦法命令在PostgreSQL的查詢結果通過IN子句中的值的順序?

+0

「_ORDER BY表達式必須出現在select list_」中 - 所以只需將表達式移動到SELECT列表:) – Karolis

回答

7

你可以把它包裝成一個派生表:

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 
1

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查詢:

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; 
0

我創建Postgres的PL/PGSQL這個功能它使用起來更容易。

-- 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; 

當你運行一個查詢,再這樣下去......

SELECT * FROM my_table ORDER BY manualidsort(my_table_id, ARRAY[25, 66, 54]) 
0

環顧我找不到這個問題的完整解決方案。

我認爲更好的解決方案是,如果你使用PostgreSQL> = 9.2可以啓用IDX功能,使擴展使用此查詢

SELECT * 
FROM items 
WHERE id IN (5,2,9) 
ORDER BY idx(array[5,2,9]::integer[], items.id) 

CREATE EXTENSION intarray; 

否則,你可以用以下命令來創建它:

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; 

我真的建議使用::integer[]查詢,因爲如果你是動態創建陣列是可能的,它導致ids(array[], items.id)沒有任何元素這會在PostgreSQL上引發異常。