Oracle订单出乎意料

时间:2019-02-21 09:52:49

标签: sql oracle sql-order-by

我有这个查询:

SELECT DISTINCT 
ID_USER, 
NUMERO, -- VARCHAR2(8 BYTE) 
NOM
FROM USER_VIEW 
WHERE UPPER(NOM) = 'JACKSON'
ORDER BY NUMERO ASC

我希望结果是这样的:

ID_USER  |   NUMERO   |   NOM
--------------------------------
1        |   TI33     |  JACKSON
9        |   TI99     |  JACKSON
4        |   1999     |  JACKSON
0        |   2001     |  JACKSON
3        |   2006     |  JACKSON
8        |   *04      |  JACKSON
5        |   *15      |  JACKSON
7        |   *61      |  JACKSON

但是我得到了不想要的结果:

ID_USER  |   NUMERO   |   NOM
--------------------------------
1        |   TI33     |  JACKSON
9        |   TI99     |  JACKSON
8        |   *04      |  JACKSON
5        |   *15      |  JACKSON
4        |   1999     |  JACKSON
0        |   2001     |  JACKSON
3        |   2006     |  JACKSON
7        |   *61      |  JACKSON

有人可以解释为什么我得到这些结果吗?以及我该如何解决?

2 个答案:

答案 0 :(得分:2)

您似乎正在使用linguistic sorting and matching,并且会话中设置的NLS_SORT(或者可能是column-level collation设置)都会导致您遇到ignorable characters。 / p>

在我的默认会话中,我看到的与您不同:

alter session set nls_sort = binary;
alter session set nls_comp = binary;

with user_view (id_user, numero, nom) as (
  select 1, cast('TI33' as varchar2(8 byte)), 'JACKSON' from dual
  union all select 9, 'TI99', 'JACKSON' from dual
  union all select 4, '1999', 'JACKSON' from dual
  union all select 0, '2001', 'JACKSON' from dual
  union all select 3, '2006', 'JACKSON' from dual
  union all select 8, '*04', 'JACKSON' from dual
  union all select 5, '*15', 'JACKSON' from dual
  union all select 7, '*61', 'JACKSON' from dual
)
SELECT DISTINCT 
ID_USER, 
NUMERO,
NOM
FROM USER_VIEW 
WHERE UPPER(NOM) = 'JACKSON'
ORDER BY NUMERO ASC
/

   ID_USER NUMERO   NOM    
---------- -------- -------
         8 *04      JACKSON
         5 *15      JACKSON
         7 *61      JACKSON
         4 1999     JACKSON
         0 2001     JACKSON
         3 2006     JACKSON
         1 TI33     JACKSON
         9 TI99     JACKSON

如果我更改设置(随机选择一种语言),那么我会这样做:

alter session set nls_sort = spanish_ci;
alter session set nls_comp = linguistic;

...

   ID_USER NUMERO   NOM    
---------- -------- -------
         1 TI33     JACKSON
         9 TI99     JACKSON
         8 *04      JACKSON
         5 *15      JACKSON
         4 1999     JACKSON
         0 2001     JACKSON
         3 2006     JACKSON
         7 *61      JACKSON

您可以使用nlssort()函数来更改会话或覆盖该列的排序:

SELECT DISTINCT 
ID_USER, 
NUMERO,
NOM
FROM USER_VIEW 
WHERE UPPER(NOM) = 'JACKSON'
ORDER BY nlssort(NUMERO, 'NLS_SORT=BINARY') ASC
/

   ID_USER NUMERO   NOM    
---------- -------- -------
         8 *04      JACKSON
         5 *15      JACKSON
         7 *61      JACKSON
         4 1999     JACKSON
         0 2001     JACKSON
         3 2006     JACKSON
         1 TI33     JACKSON
         9 TI99     JACKSON

但这仍然将*值放在第一位。

您可能必须使用case表达式来解决此问题:

SELECT DISTINCT 
ID_USER, 
NUMERO,
NOM
FROM USER_VIEW 
WHERE UPPER(NOM) = 'JACKSON'
ORDER BY CASE WHEN SUBSTR(NUMERO, 1, 1) = '*' then 2 else 1 end, NUMERO
/

   ID_USER NUMERO   NOM    
---------- -------- -------
         1 TI33     JACKSON
         9 TI99     JACKSON
         4 1999     JACKSON
         0 2001     JACKSON
         3 2006     JACKSON
         8 *04      JACKSON
         5 *15      JACKSON
         7 *61      JACKSON
  

我有一个框架,可以根据GUI中的按钮将ASC或DESC附加到自定义查询,而且我无法触摸该框架以使其也改变大小写表达式中的值

然后,您可以将大小写表达式结果连接起来(以字符串而不是数字,以及在排序规则中真正以正确顺序排列的任何字符);当您通过单个组合表达式排序时,可以按升序排序:

SELECT DISTINCT 
ID_USER, 
NUMERO,
NOM
FROM USER_VIEW 
WHERE UPPER(NOM) = 'JACKSON'
ORDER BY CASE WHEN SUBSTR(NUMERO, 1, 1) = '*' then 'B' else 'A' end || NUMERO ASC
/

   ID_USER NUMERO   NOM    
---------- -------- -------
         1 TI33     JACKSON
         9 TI99     JACKSON
         4 1999     JACKSON
         0 2001     JACKSON
         3 2006     JACKSON
         8 *04      JACKSON
         5 *15      JACKSON
         7 *61      JACKSON

...或降序:

SELECT DISTINCT 
ID_USER, 
NUMERO,
NOM
FROM USER_VIEW 
WHERE UPPER(NOM) = 'JACKSON'
ORDER BY CASE WHEN SUBSTR(NUMERO, 1, 1) = '*' then 'B' else 'A' end || NUMERO DESC
/

   ID_USER NUMERO   NOM    
---------- -------- -------
         7 *61      JACKSON
         5 *15      JACKSON
         8 *04      JACKSON
         3 2006     JACKSON
         0 2001     JACKSON
         4 1999     JACKSON
         9 TI99     JACKSON
         1 TI33     JACKSON

答案 1 :(得分:0)

您可以使用:

select ID_USER, NUMERO, NOM 
from user_view
WHERE UPPER(NOM) = 'JACKSON'
order by replace(numero,'*','')