我需要将属于某些范围的数字列表转换为值列表,按优先级列排序。该表具有以下值:
| 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查询中进行。
要在Oracle数据库中运行哪个SQL查询会给我想要的结果?
(注意,这不是关于splitting an input string,而是将值列表中的每个值与不同列中定义的范围相匹配。)
答案 0 :(得分:4)
我猜你想把这组数字作为字符串传递并分成单个数字。这比你想象的要难,因为Oracle没有内置的tokenizer。很奇怪,是吗?
有许多PL / SQL标记器解决方案可以解决Das Interwabs问题。我正在使用Anup Pani's implementation的变体,它使用Regex(因此只有Oracle 10g或更高版本)。我的变量返回一个数组,我已声明为SQL类型:
SQL> create or replace type numbers as table of number
2 /
Type created.
SQL>
这意味着我可以将它用作SELECT语句中TABLE()函数的输入:
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 :(得分:1)
我认为您的第一个任务是将数字列表转换为可以加入的结果集(即内存表)。我不了解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。