SQL-запрос для перевода списка чисел, сопоставленных с несколькими диапазонами, в список значений - PullRequest
1 голос
/ 14 апреля 2010

Мне нужно преобразовать список чисел, попадающих в определенные диапазоны, в список значений, упорядоченный по приоритетному столбцу. Таблица имеет следующие значения:

| YEAR | R_MIN |  R_MAX | VAL | PRIO |
------------------------------------
  2010   18000    90100   52    6
  2010  240000   240099   82    3
  2010  250000   259999   50    5
  2010  260000   260010   92    1
  2010  330000   330010   73    4
  2010  330011   370020   50    5
  2010  380000   380050   84    2

Диапазоны будут разными для разных лет. Диапазоны в течение одного года никогда не будут перекрываться.

В качестве ввода будет указан год и список чисел, которые могут попадать в один из этих диапазонов. Список вводимых номеров будет небольшим, от 1 до 10 номеров. Пример ввода чисел:

(20000, 240004, 375000, 255000)

С этим вводом я хотел бы получить список, упорядоченный по приоритетному столбцу, или одно значение:

82
50
52

Единственное значение, которое меня здесь интересует, это 82 , поэтому UNIQUE и MAX_RESULTS = 1 подойдут. Это легко сделать с помощью одного запроса на число, а затем отсортировать его в коде Java, но я бы предпочел сделать это в одном запросе SQL.

Какой запрос SQL, который будет выполняться в базе данных Oracle, даст мне желаемый результат?

(Обратите внимание, что речь идет не о разбиении входной строки , а о сопоставлении каждого значения в списке значений с диапазонами, определенными в разных столбцах.)

Ответы [ 2 ]

4 голосов
/ 14 апреля 2010

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

В Das Interwabs есть несколько решений для токенизаторов PL / SQL. Я использую вариант реализации Anup Pani , который использует Regex (следовательно, только Oracle 10g или выше). Мой вариант возвращает массив чисел, который я объявил как тип SQL:

SQL> create or replace type numbers as table of number
  2  /

Type created.

SQL>

Это означает, что я могу использовать его как вход для функции TABLE () в инструкции SELECT:

SQL> select * from table (str_to_number_tokens('20000, 240004, 375000, 255000'))
  2  /

COLUMN_VALUE
------------
       20000
      240004
      375000
      255000

SQL>

Это означает, что я могу превратить вашу строку чисел в таблицу, к которой я могу присоединиться в запросе, например:

SQL> select val
  2  from t23
  3       , ( select column_value as i_no
  4           from table (str_to_number_tokens('20000, 240004, 375000, 255000')) ) sq
  5  where t23.year = 2010
  6  and   sq.i_no between t23.r_min and t23.r_max
  7  order by t23.priority
  8  /

       VAL
----------
        82
        50
        52

SQL>
1 голос
/ 14 апреля 2010

Я думаю, что вашей первой задачей было бы преобразовать список чисел в набор результатов (то есть в таблицу в памяти), к которому вы можете присоединиться. Я не знаю Oracle, поэтому может быть простой способ сделать это, но если нет, то вам нужно написать какую-то определенную пользователем функцию, которая делает это. Это не должно быть слишком сложно, и производительность не является проблемой, так как список невелик. Затем вы можете присоединиться к этой таблице. Примерно так:

SELECT yt.val
FROM your_table yt
JOIN your_parse_numbers_function(@inputlist) il
ON il.value >= yt.R_MIN AND il.value <= yt.R_MAX
WHERE yt.YEAR = @year

Если хотите, вы можете ограничить этот результат до 1, но если ваше предположение о диапазонах, не перекрывающихся, верное, то в любом случае оно должно возвращать только 1.

...