Как получить максимум (0,10) +1 как 0,11 в Oracle SQL - PullRequest
1 голос
/ 20 апреля 2020

У меня есть значения 0,0, 0,1, 0,2 в таблице. Я использовал запрос ниже, чтобы заполнить таблицу 0,0, 0,4, ... 0,10.

Я пытаюсь добавить еще 4 записи в таблицу и ожидаю, что значения будут 0,11, 0,12, 0,13, 0,14. Но мой запрос заполнил их все как 0.10, поэтому дублирует.

Ниже приведен мой запрос, и, пожалуйста, помогите мне решить эту проблему.

- Запрос

SELECT nvl(MAX(substr(sequence_number, instr(sequence_number, '.') + 1, 1)) + 1, '0') 
FROM TESTING_TBL;

- - Примеры сценариев создания таблиц

CREATE TABLE TESTING_TBL (SEQUENCE_NUMBER VARCHAR2(30));
INSERT ALL INTO TESTING_TBL ( sequence_number ) VALUES ( '0.0' )
    INTO  TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.1')
    INTO  TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.2')
    INTO  TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.3')
    INTO  TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.4')
    INTO  TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.5')
    INTO  TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.6')
    INTO  TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.7')
    INTO  TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.8')
    INTO  TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.9')
    INTO  TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.10')
SELECT '1' FROM dual;

Спасибо!

Ответы [ 3 ]

0 голосов
/ 20 апреля 2020

Оставляя в стороне различные разумные комментарии о том, является ли это даже хорошей идеей ...

Непосредственная проблема заключается в том, что вы ограничиваете длину подстроки 1:

SELECT nvl (MAX (substr (sequence_number, instr (sequence_number, '.') + 1 , 1 )) + 1, '0')

Когда есть только 1 di git после десятичная дробь, это отлично работает, так что вы получаете до 0.10. В этот момент substr возвращает «1», а не «10», как вы, вероятно, хотите. Полагаю, это приводит к тому, что вы пытаетесь снова вставить «0.2», вызывая нарушение уникальности.

Если это работает для всех ваших входов, вам просто нужно удалить этот параметр длины. Но если вам нужно обрабатывать более сложные строки, такие как, скажем, «0.10.3», вам может потребоваться использовать регулярные выражения для анализа. Или, как предлагают другие, сохраните подкомпоненты этой строки в виде отдельного значения цифры c и объедините их, используя виртуальный столбец или во время вставки в финальную таблицу.

0 голосов
/ 21 апреля 2020

Спасибо всем за то, что уделили мне время. Цените все ваши усилия.

Я разделил до и после десятичных чисел и использовал запрос ниже, чтобы увеличить после десятичного числа. Это решило мою проблему.

SELECT NVL(MAX(SUBSTR(sequence_number, 3)+1),'0')
FROM TESTING_TBL;
0 голосов
/ 20 апреля 2020

Сначала необходимо разбить строку на две части, затем преобразовать обе части в числа и применить MAX и увеличить на 1.

Это пример запроса

with tbl as (
select 
  SEQUENCE_NUMBER,
  to_number(substr(SEQUENCE_NUMBER,1,instr(SEQUENCE_NUMBER,'.')-1)) num1,
  to_number(substr(SEQUENCE_NUMBER,instr(SEQUENCE_NUMBER,'.')+1)) num2
from TESTING_TBL)
select SEQUENCE_NUMBER, NUM1, NUM2
from tbl
order by num1, num2;

давая данные как

SEQUENCE_NUMBER                      NUM1       NUM2
------------------------------ ---------- ----------
0.0                                     0          0
0.1                                     0          1
....
0.8                                     0          8
0.9                                     0          9
0.10                                    0         10

Теперь с помощью цифр вы можете безопасно найти МАКС и добавить 1

with tbl as (
select 
  SEQUENCE_NUMBER,
  to_number(substr(SEQUENCE_NUMBER,1,instr(SEQUENCE_NUMBER,'.')-1)) num1,
  to_number(substr(SEQUENCE_NUMBER,instr(SEQUENCE_NUMBER,'.')+1)) num2
from TESTING_TBL)
select to_char(max(NUM1))||'.'||to_char(max(NUM2)+1) new_key
from tbl

, что дает ожидаемый результат

NEW_KEY                                                                          
---------------------------------------------------------------------------------
0.11 

Обратите внимание, что вы следует пересмотреть свой дизайн, если это оптимальный подход. В качестве лучшего и более безопасного варианта я бы рассмотрел хранение двух столбцов INT (введите safe!) И определение представления текста только как виртуальный столбец:

CREATE TABLE TESTING_TBL2 (num1 int, num2 int);

alter table TESTING_TBL2 add  SEQUENCE_NUMBER AS (to_char(num1)||'.'||to_char(num2)) VIRTUAL  ;

добавить тестовые данные

INSERT ALL INTO TESTING_TBL2 ( num1, num2 ) VALUES ( 0,0 )
-- ....
    INTO  TESTING_TBL2 (num1, num2) VALUES ( 0,9 )
    INTO  TESTING_TBL2 (num1, num2) VALUES ( 0,10)
SELECT '1' FROM dual;

теперь этот простой запрос предоставляет новые ключи

select max(num1) num1, max(num2)+1 num2 from TESTING_TBL2;

Полные данные

select * from TESTING_TBL2;

      NUM1       NUM2 SEQUENCE_NUMBER                                                                  
---------- ---------- ------------------- 
         0          0 0.0                                                                              
         0          9 0.9                                                                              
         0         10 0.10        

Помните также, что алгоритм MAX + 1 для распределения новых ключей лучше всего работает в одиночном пользователь enviromnemt.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...