#sql #plsql #oracle11g #sql-order-by #oracle12c
#sql #plsql #oracle11g #sql-order-by #oracle12c
Вопрос:
У меня есть хранимая процедура Oracle, которая отвечает за разбивку данных запроса на страницы. Он получает текст для поиска, смещение и номер страницы. Теперь я хочу добавить два новых параметра для сортировки результата запроса перед разбиением его на страницы. Мой вопрос в том, как я могу указать динамический порядок и направление.
На данный момент, я думаю, что я должен использовать предложение CASE для указания столбца, но мне нужно добавить, является ли это ASC или DESC.
CREATE OR REPLACE PROCEDURE search_city_paged (
in_search_key IN VARCHAR2,
in_offset IN NUMBER,
in_num_elements IN NUMBER,
in_polling_place IN VARCHAR2,
in_order_by IN NUMBER,
in_order_dir IN VARCHAR2,
out_city OUT SYS_REFCURSOR
) AS
BEGIN
OPEN out_citizens FOR
SELECT COUNT(*) OVER (),
cit.city_code,
cit.city_name,
cit.city_zip,
cit.city_cities
FROM city cit
WHERE CATSEARCH(cit.FULL_TEXT_SEARCH, l_in_search_key, NULL)>0
ORDER BY ???
OFFSET in_offset ROWS FETCH FIRST in_num_elements ROWS ONLY;
END search_city_paged;
Если я получу в новых параметрах 1 и ASC, результат будет отсортирован по коду city_code ASC.
Если я получу в новых параметрах 1 и DESC, результат будет отсортирован по city_code DESC.
Если я получу в новых параметрах 2 и ASC, результат будет отсортирован по имени city_name ASC.
Если я получу в новых параметрах 2 и DESC, результат будет отсортирован по имени city_name DESC.
И… таким же образом в каждом столбце я должен разрешить сортировку результатов.
Ответ №1:
Порядок по двум внешним CASE
выражениям, одному ASC
one DESC
. В первом из них проверьте, хотите ли вы выполнить сортировку ASC
, и если нет, пусть выражение возвращает константу or NULL
, т.е. порядок не меняется. Для случая, когда вы хотите отсортировать, ASC
добавьте внутреннее CASE
выражение, которое возвращает столбец для сортировки. Аналогично обработайте DESC
случай.
...
ORDER BY CASE
WHEN in_order_dir = 'ASC' THEN
CASE
WHEN in_order_by = 1 THEN
city_code
WHEN in_order_by = 2 THEN
city_name
...
END
END ASC,
CASE
WHEN in_order_dir = 'DESC' THEN
CASE
WHEN in_order_by = 1 THEN
city_code
WHEN in_order_by = 2 THEN
city_name
...
END
END DESC;
Возможно, вам придется адаптировать его из-за несовместимости типов между столбцами, я не могу сказать этого из того, что вы опубликовали. Но это должно передавать общую концепцию.
Редактировать:
О проблеме типа:
Одна из возможностей заключается в преобразовании столбцов в совместимые типы данных таким образом, чтобы порядок сохранялся. Например, если у вас есть char_column
(типа char
), date_column
и integer_column
(из date
и integer
), вы могли бы сделать
to_char(date_column, 'YYYYMMDDHH24MISS')
для преобразования даты и
lpad(11, 38, '0')
для преобразования целого числа в char
.
Самое простое, что нужно сделать, но требующее больше работы (для программиста, с точки зрения производительности, не должно быть никакой существенной разницы вообще), — это еще раз разделить выражения. Т.Е. иметь внешнее CASE
значение для каждого типа, ваши столбцы для каждого направления.
Нравится
ORDER BY CASE
WHEN in_order_dir = 'ASC' THEN
CASE
WHEN in_order_by = 1 THEN
char_column1
WHEN in_order_by = 2 THEN
char_column2
...
END
END ASC,
CASE
WHEN in_order_dir = 'ASC' THEN
CASE
WHEN in_order_by = 3 THEN
date_column1
WHEN in_order_by = 4 THEN
date_column2
...
END
END ASC,
и так далее для всех типов и аналогично для DESC
. Помните, что если столбец не предназначен для сортировки после такого, то CASE
это даст NULL
результат, и сортировка по этому не повлияет на порядок.
Комментарии:
1. Пара дополнительных вопросов, как я могу добавить более одного столбца в регистр? и когда я использую столбцы типа specify date, он выдает «ORA-00932: несовместимые типы данных: ожидаемая ДАТА получения СИМВОЛА», как я могу указать порядок по датам?
2. Спасибо, это было действительно полезно.