2014-01-02 3 views
0

У меня есть таблица Аннотация, которая имеет один из столбцов (SerialNumber). Он имеет данные, как показано ниже.Пользовательский сортировка с чередой чисел (последовательностей) с использованием oracle sql

1 
1.1 
1.1.1 
1.1.2 
1.2 
.. 
.. 
10 
10.1 
10.2 

Теперь мое требование состоит в том, чтобы сортировать данные на основе этого столбца в качестве первого предпочтения. Максимум 2 "точки" возможны в SerialNumber.

So 1.2.3.4 невозможно. Максимальный номер может быть 999 на любом уровне. т.е. 999.999.999 - максимально возможная последовательность.

Я пытался путем выдачи ORDER BY SerialNumber, он приходит как

1 
10 
10.1 
.. 
2 
2.1 

Просто из-за характера своего рода, а не 2, 10 приходит после 1. Любая идея о том, как это можно достичь.? Так как мне это нужно в JDBC и в нескольких запросах (в разных модулях), надеясь получить это как можно более общее.

+1

Получить подстроки каждого числового компонента и масштаб с силой 10, то dd их всех, и сортировать. – OldProgrammer

+1

'LPAD'' 0' с каждым номером внутри .. так что вы можете сделать сортировку символов .. пример '1.1.1' как' 001.001.001' –

+0

Помогло ли регулярное выражение? Извините, я не очень хорош в этом. –

ответ

0

Функция для извлечения каждого номера с использованием '.' в качестве разделителя и LPAD с 0s. И вызовите функцию() в order by

CREATE OR REPLACE FUNCTION FORMAT_MY_SERIAL(
    ORIG_SERIAL VARCHAR2) 
    RETURN VARCHAR2 
AS 
    FINAL_SERIAL VARCHAR2(15) := ''; 
    SERIAL  VARCHAR2(15); 
BEGIN 
    SERIAL     := ORIG_SERIAL; 
    WHILE (INSTR(SERIAL,'.') <> 0) 
    LOOP 
    FINAL_SERIAL := TO_CHAR(SUBSTR(SERIAL,INSTR(SERIAL,'.',-1)+1),'FM099')||'.'||FINAL_SERIAL; 
    SERIAL  := SUBSTR(SERIAL,1,INSTR(SERIAL,'.',-1)-1); 
    END LOOP; 
    FINAL_SERIAL := TRIM(BOTH '.' FROM TO_CHAR(SERIAL,'FM099')||'.'||FINAL_SERIAL); 
    RETURN FINAL_SERIAL; 
END FORMAT_MY_SERIAL; 
/

И это пример:

WITH MY_TABLE AS 
    (SELECT '1.1.1' AS SerialNumber FROM dual 
    UNION ALL 
    SELECT '10' FROM dual 
    UNION ALL 
    SELECT '1' FROM dual 
    UNION ALL 
    SELECT '1.2' FROM dual 
    UNION ALL 
    SELECT '2.1' FROM dual 
    UNION ALL 
    SELECT '1.10.1' FROM dual 
    UNION ALL 
    SELECT '2.1' FROM dual 
) 
SELECT SerialNumber, 
    FORMAT_MY_SERIAL(SerialNumber) as formatted 
FROM MY_TABLE 
ORDER BY FORMAT_MY_SERIAL(SerialNumber); 

Результат:

SERIAL FORMATTED 
1  001 
1.1.1 001.001.001 
1.2 001.002 
1.10.1 001.010.001 
2.1 002.001 
2.1 002.001 
10  010 
+0

Похоже, что он поддерживает любое количество уровней и размера номера, регулируя переменный размер (!) .. –

+0

да .. нужно изменить код, только для модели формата, сохранить размер номера коротким n сладким, безопасным :) создать индекс на основе функции , или сохранить то же самое в таблице! он многоразовый .. –

3

Я бы, вероятно, использовал функцию регулярного выражения для разделения каждой части для заказа. Что-то вроде:

select serialnumber 
from data 
order by 
    to_number(regexp_substr(serialnumber, '[[:digit:]]+')), 
    to_number(regexp_substr(serialnumber, '[[:digit:]]+', 1, 2)) nulls first, 
    to_number(regexp_substr(serialnumber, '[[:digit:]]+', 1, 3)) nulls first 

который даст вам результаты, как:

SERIALNUMBER                  
------------------------------- 
1.100                   
1.100.10                   
34.134.819                  
36                    
75.717                   
256.749.864                  
397                    
428.13.647                  
443                    
713.768                   
855.238  
0
create table temp as select dummy from dual; 

alter table temp add val varchar2(20); 

select * from temp; 

insert into temp (val) values ('1'); 
insert into temp (val)values ('1.2'); 
insert into temp (val)values ('1.1.1'); 
insert into temp (val)values ('2'); 
insert into temp (val)values ('2.1'); 
insert into temp (val)values ('10'); 

select val 
    ,decode(substr(val,1,instr(val,'.')-1),null,val,substr(val,1,instr(val,'.')-1)) 
from temp 
order by  to_number(decode(substr(val,1,instr(val,'.')-1),null,val,substr(val,1,instr(val,'.')-1))),val 
Смежные вопросы