У меня есть база данных, в которой каждая транзакция получает буквенно-цифровой идентификатор. Когда я пишу свой запрос и использую Order by it, я получаю неправильную последовательность.
Например:
TRN_ID TRNDTE
000002DAAW 2020-09-12 03:45:24
000002DAAX 2020-09-12 03:45:32
000002DAAY 2020-09-12 03:45:34
000002DAAZ 2020-09-12 03:45:38
000002DAA0 2020-09-12 03:35:16
000002DAA1 2020-09-12 03:35:25
000002DAA2 2020-09-12 03:35:26
000002DAA3 2020-09-12 03:35:30
000002DAA4 2020-09-12 03:35:39
000002DAA5 2020-09-12 03:35:40
000002DAA6 2020-09-12 03:35:44
000002DAA7 2020-09-12 03:36:00
000002DAA8 2020-09-12 03:36:01
000002DAA9 2020-09-12 03:36:05
000002DABA 2020-09-12 03:48:12 <-
000002DABB 2020-09-12 03:48:15
000002DABC 2020-09-12 03:48:32
000002DABD 2020-09-12 03:48:33
000002DABE 2020-09-12 03:48:36
000002DABF 2020-09-12 03:48:46
000002DABG 2020-09-12 03:48:47
000002DABH 2020-09-12 03:48:50
000002DABI 2020-09-12 03:49:06
000002DABJ 2020-09-12 03:49:06
000002DABK 2020-09-12 03:49:09
000002DABL 2020-09-12 03:49:19
000002DABM 2020-09-12 03:49:20
000002DABN 2020-09-12 03:49:24
000002DABO 2020-09-12 03:49:33
000002DABP 2020-09-12 03:49:34
000002DABQ 2020-09-12 03:49:37
000002DABR 2020-09-12 03:49:48
000002DABS 2020-09-12 03:49:48
000002DABT 2020-09-12 03:49:51
000002DABU 2020-09-12 03:50:01
000002DABV 2020-09-12 03:50:01
000002DABW 2020-09-12 03:50:05
000002DABX 2020-09-12 03:50:15
000002DABY 2020-09-12 03:50:15
000002DABZ 2020-09-12 03:50:18
000002DAB0 2020-09-12 03:46:23 <-
000002DAB1 2020-09-12 03:46:24
000002DAB2 2020-09-12 03:46:28
000002DAB3 2020-09-12 03:47:18
000002DAB4 2020-09-12 03:47:18
Как видите, запрос упорядочивает от А до Я, затем от 0 до 9, но он должен упорядочивать от 0 до 9, затем от А до Я.
Есть ли способ установить строку, чтобы правильно ее упорядочить?
Что вы получаете, когда бегаете select parameter, value from v$nls_parameters WHERE parameter IN ( 'NLS_LANGUAGE', 'NLS_SORT');
? Эффект ORDER BY
зависит от этих параметров.
Тринкот (вверху) делает отличное замечание. Во французском, например, буквы сортируются перед цифрами. Это первое место, где нужно искать объяснение.
@mathguy Извините, я забыл упомянуть, я думал, что это не имеет значения. Я использую чистый обычный: ORDER BY TRN_ID
Я сделал это, потому что есть некоторые данные, которые сохраняются в ту же секунду, и база данных не дает мне миллисекунд для их сортировки.
@trincot Я попробую ваше решение в понедельник, как только вернусь к работе! Я дам вам знать! Я верю, что это может помочь, как упомянул @mathguy!
Тринкот не предложил решения — он лишь предложил возможную причину того, что вы видите. Решение подскажет вам, что делать с проблемой — как обойти проблему, которая определена как причина вашей проблемы.
Весьма вероятно, что наблюдение Тринкота (второй комментарий к вашему вопросу) верно: вы видите упорядочение по возрастанию с буквами перед цифрами (а не наоборот), потому что этого требует ваша сортировка.
Судя по вашему профилю, я предполагаю, что вы находитесь в Бразилии, и ваш параметр NLS_LANGUAGE
равен 'BRAZILIAN PORTUGUESE'
, а параметр NLS_SORT
по умолчанию (производный от NLS_LANGUAGE
) равен 'WEST_EUROPEAN'
. Это не выбор Oracle; В бразильской португальской сортировке (или, точнее, в западноевропейской сортировке) цифры стоят после букв, а не перед ними. См. демо в конце этого ответа.
Итак, это объясняет проблему. Как это исправить?
Если у вас много похожих запросов, и вы должны показывать цифры перед буквами во всех из них (или если у вас есть ORDER BY
во многих местах в запросе - например, в аналитических функциях, или в match_recognize
и т. д.), то это делает смысла менять параметр NLS_SORT
для сеанса, с
alter session set nls_sort='BINARY';
Если вам нужно сделать это только в одном запросе, в предложении ORDER BY
, вы можете просто изменить порядок сортировки локально (только для этого предложения ORDER BY
, не затрагивая ничего другого) с помощью функции NLSSORT
. Так:
.... order by nlssort(TRN_ID, 'NLS_SORT=BINARY')
Вот краткая демонстрация.
Во-первых, в моей системе NLS_LANGUAGE
— это 'AMERICAN'
, а по умолчанию NLS_SORT
(для этого языка) — 'BINARY'
. Вот почему буквы идут после цифр:
select col
from (select 'A' as col from dual union all select '3' from dual)
order by col;
COL
---
3
A
Теперь позвольте мне изменить мой NLS_LANGUAGE
на 'BRAZILIAN PORTUGUESE'
. Затем давайте посмотрим, как это повлияло на NLS_SORT
(автоматически) и как это повлияло на запрос:
alter session set nls_language='BRAZILIAN PORTUGUESE';
select parameter, value
from v$nls_parameters
where parameter in ('NLS_LANGUAGE', 'NLS_SORT');
PARAMETER VALUE
------------ ----------------------
NLS_LANGUAGE BRAZILIAN PORTUGUESE
NLS_SORT WEST_EUROPEAN
select col
from (select 'A' as col from dual union all select '3' from dual)
order by col;
COL
---
A
3
Теперь, не меняя языка, позвольте мне просто изменить последовательность сопоставления (параметр NLS_SORT
) на 'BINARY'
— и посмотреть, как запрос выдает желаемый результат. Мы не меняли язык, но мы изменили последовательность сопоставления для всего сеанса. Это будет работать для всех других запросов в текущем сеансе.
alter session set nls_sort='BINARY';
select parameter, value
from v$nls_parameters
where parameter in ('NLS_LANGUAGE', 'NLS_SORT');
PARAMETER VALUE
------------ ----------------------
NLS_LANGUAGE BRAZILIAN PORTUGUESE
NLS_SORT BINARY
select col
from (select 'A' as col from dual union all select '3' from dual)
order by col;
COL
---
3
A
Наконец, позвольте мне изменить NLS_SORT
обратно на 'WEST_EUROPEAN'
и использовать функцию NLSSORT
в предложении ORDER BY
запроса, чтобы получить тот же результат (тот, который вам нужен), не касаясь параметров сеанса.
alter session set nls_sort='WEST_EUROPEAN';
select col
from (select 'A' as col from dual union all select '3' from dual)
order by col; -- This will produce the wrong order! See below for fix.
COL
---
A
3
select col
from (select 'A' as col from dual union all select '3' from dual)
order by nlssort(col, 'nls_sort=BINARY');
COL
---
3
A
Что ж, мы не видим вашего запроса, так как вы ожидаете, что мы вам поможем? Вы должны по крайней мере скопировать и вставить предложение ORDER BY из вашего запроса.