Прежде всего, @order
не является допустимым синтаксисом PostgreSQL. Вы, вероятно, позаимствовали стиль синтаксиса у MS SQL Server или MySQL. Вы не можете использовать переменные в простом SQL-запросе, подобном этому.
В PostgreSQL вы, вероятно, создадите функцию . Вы можете использовать переменные там, просто бросьте @
.
Сортировка по ARRAY , как правило, довольно медленная - и не требуется в вашем случае. Вы можете упростить до:
ORDER BY
CASE _order
WHEN 1 THEN c2
WHEN 2 THEN c3 * -1
ELSE NULL -- undefined!
END
, c1
Однако , подобное выражение CASE не может использовать простые индексы. Итак, если вы ищете производительность, одним из способов (из нескольких) будет функция plpgsql , например:
CREATE OR REPLACE FUNCTION foo(int)
RETURNS TABLE(c1 int, c2 int) AS
$BODY$
BEGIN
CASE $1
WHEN 1 THEN
RETURN QUERY
SELECT t.c1, t.c2
FROM tbl t
ORDER BY t.c2, t.c1;
WHEN 2 THEN
RETURN QUERY
SELECT t.c1, t.c2
FROM tbl t
ORDER BY t.c3 DESC, t.c1;
ELSE
RAISE WARNING 'Unexpected parameter: "%"', $1;
END CASE;
END;
$BODY$
LANGUAGE plpgsql STABLE;
Таким образом, можно использовать даже простые индексы.
Если у вас есть только две альтернативы для ORDER BY, вы также можете просто написать две
функции.
Создание многостолбцовых индексов для (c2, c1)
и (c3 DESC, c1)
для максимальной производительности. Но имейте в виду, что поддержание индексов также сопряжено с затратами, особенно если в вашей таблице много операций записи.
Дополнительный ответ на перефразированный вопрос
Как я уже сказал, конструкция CASE не будет использовать простые индексы. Индексы для выражений будет вариант, но то, что у вас есть в вашем примере, выходит за рамки.
Итак, если вам нужна производительность, создайте запрос в своем приложении (ваш первый подход) или напишите функцию на стороне сервера (возможно, с динамическим SQL и EXECUTE ), которая делает нечто подобное внутри PostgreSQL. Предложение WHERE
со сложным оператором CASE
работает, но медленнее.