我在下面的列中有一个逗号分隔的字符串作为值。
'2015/04/01 11 GG, 2015/08/03 78 KK, 2012/12/12 44 TT, 2015/09/01 77 YY, 2015/09/01 88 ZZ'
其中,每个字符串都有三列,并以空格分隔。
因此,这里的要求是选择更大或更接近给定输入日期的日期 并获得第二列。
示例: 如果输入日期为 2015年8月1日,则我的输出应为 78 ,因为它的日期比较接近。 如果没有日期大于输入日期,则输出应为空。
答案 0 :(得分:3)
这是一个复杂的要求,正如戈登·利诺夫(Gordon Linoff)所说,如果数据已经正确传播,则解决起来会容易得多。
这是一种方法:
REGEXP_SUBSTR
和CONNECT BY
的递归CTE,使用逗号分隔符将字符串分成几行REGEXP_SUBSTR
和空格分隔符DENSE_RANK
和KEEP
隔离相关行假设数据来自表str
的列my_table
:
WITH
cte0 AS (
SELECT TRIM(REGEXP_SUBSTR(str, '[^,]+', 1, LEVEL)) str
FROM my_table
CONNECT BY INSTR(str, ',', 1, LEVEL - 1) > 0
),
cte1 AS (
SELECT
TO_DATE(REGEXP_SUBSTR(str, '\S+', 1, 1), 'yyyy-mm-dd') dt,
REGEXP_SUBSTR(str, '\S+', 1, 2) val1,
REGEXP_SUBSTR(str, '\S+', 1, 3) val2
FROM cte0
ORDER BY 1 DESC
)
SELECT
MIN(dt) keep (dense_rank first order by dt) as dt,
MIN(val1) keep (dense_rank first order by dt) as val1,
MIN(val2) keep (dense_rank first order by dt) as val2
FROM cte1
WHERE dt > TO_DATE(?, 'yyyy-mm-dd')
...,其中?
是输入日期。
with
data as (
SELECT
'2015/04/01 11 GG, 2015/08/03 78 KK, 2012/12/12 44 TT, 2015/09/01 77 YY, 2015/09/01 88 ZZ' str
FROM DUAL
),
cte0 AS (
SELECT TRIM(REGEXP_SUBSTR(str, '[^,]+', 1, LEVEL)) str
FROM data
CONNECT BY INSTR(str, ',', 1, LEVEL - 1) > 0
),
cte1 AS (
SELECT
TO_DATE(REGEXP_SUBSTR(str, '\S+', 1, 1), 'yyyy-mm-dd') dt,
REGEXP_SUBSTR(str, '\S+', 1, 2) val1,
REGEXP_SUBSTR(str, '\S+', 1, 3) val2
FROM cte0
ORDER BY 1 DESC
)
SELECT
min(dt) keep (dense_rank first order by dt) as dt,
min(val1) keep (dense_rank first order by dt) as val1,
min(val2) keep (dense_rank first order by dt) as val2
FROM cte1
WHERE dt > TO_DATE('2015-08-01', 'yyyy-mm-dd')
-------------------------
DT | VAL1 | VAL2
:-------- | :--- | :---
03-AUG-15 | 78 | KK
答案 1 :(得分:1)
根据您提供的示例数据,这是一个选择。
SQL> with test (col) as
2 (select '2015/04/01 11 GG, 2015/08/03 78 KK, 2012/12/12 44 TT, 2015/09/01 77 YY, 2015/09/01 88 ZZ' from dual),
3 t_comma as
4 (select trim(regexp_substr(col, '[^,]+', 1, level)) col2
5 from test
6 connect by level <= regexp_count(col, ',') + 1
7 ),
8 t_diff as
9 (select col2,
10 substr(col2, 1, 10) c_date,
11 regexp_substr(col2, '\d+', 1, 4) c_num,
12 regexp_substr(col2, '\w+$') c_let ,
13 --
14 abs(to_date(substr(col2, 1, 10), 'yyyy/mm/dd') -
15 to_date('&&:par_date', 'yyyy/mm/dd')) diff_days,
16 --
17 row_number() over (order by abs(to_date(substr(col2, 1, 10), 'yyyy/mm/dd') -
18 to_date('&&par_date', 'yyyy/mm/dd'))) rn
19 from t_comma
20 )
21 select c_num
22 from t_diff
23 where rn = 1;
Enter value for par_date: 2015-08-01
C_NUM
--------------------------------------------------------------------------------
78
SQL>
它是做什么的?
TEST
是您的示例表(由CTE表示)T_COMMA
将逗号分隔的值字符串分成几行(这样您就可以从示例数据中获得5行)T_DIFF
提取子字符串的每个部分(即每一行),计算采样日期和参数化日期之间的差,并按差的绝对值对其进行排名-RN = 1
是“最接近的” “日期SELECT
仅返回“最接近”的值