在 oracle 11g 中将数据类型排序为 varchar2 的日期字段
sorting date field with datatype as varchar2 in oracle 11g
我需要对日期值为数字格式的 varchar2 数据类型列进行排序,格式为 YYMM
到 MMYY
取值范围为
3
6
9
12
103
.
.
9909
9912
长度为4个字符的值表示1900到1999之间的年份
少于4个字符表示年份以2000年及以上开始。
我尝试使用 LPAD(fieldname, 4,'0'),其中 returns 值为
0003 this is nothing but 2000/03
0006 ------------------- 2000/06
0009
0012
0103 ------------------- 2001/03
.
.
9912 ------------------- 1999/12
如何根据从 1900 年开始的年份值按升序对列进行排序。
谁能给我解决方案....
您需要先区分现有的四位数字值,以便在填充其余部分之前知道它们是 20 世纪的日期。
然后将其转换为日期和 fiddle 格式以获得您需要的排序顺序:
select to_char( expanded_dt, 'MMYYYY') as switched_dt
from (
select to_date(
case when length(dt) = 4 then '19'||dt
else '20'||lpad(dt,4,'0') end
, 'YYYYMM' )
as expanded_dt
from your_table
)
order by 1 asc
/
首先,将 DATE 值存储为 VARCHAR2 并仅使用 部分元素。在漫长的运行中,你应该首先修复你的设计。
作为解决方法,如果年份值在 1950-2049
范围内,您可以使用 RR
格式作为 两位数字年.
TO_DATE(LPAD(date_column, 4,'0'), 'RRMM')
LPAD
将添加所需的前导零。
例如,
SQL> alter session set nls_date_format='MM/DD/YYYY';
Session altered.
SQL> WITH dates AS(
2 SELECT '3' dt FROM dual UNION ALL
3 SELECT '6' dt FROM dual UNION ALL
4 SELECT '9' dt FROM dual UNION ALL
5 SELECT '12' dt FROM dual UNION ALL
6 SELECT '103' dt FROM dual UNION ALL
7 SELECT '9909' dt FROM dual UNION ALL
8 SELECT '9912' dt FROM dual
9 )
10 SELECT dt,
11 TO_DATE(LPAD(dt, 4,'0'), 'RRMM') date_val
12 FROM dates
13 ORDER BY date_val;
DT DATE_VAL
---- ----------
9909 09/01/1999
9912 12/01/1999
3 03/01/2000
6 06/01/2000
9 09/01/2000
12 12/01/2000
103 03/01/2001
7 rows selected.
SQL>
因此,上面的查询为您提供了所需的输出,日期值现在按升序排序。
您可以根据值的长度添加一个世纪标记:
select value,
case when length(value) = 4 then '19' else '20' end || lpad(value, 4, '0') as dt
from t
order by case when length(value) = 4 then '19' else '20' end || lpad(value, 4, '0');
VALUE DT
---------- ------
9909 199909
9912 199912
6 200006
9 200009
12 200012
103 200103
或者使用相同的东西并转换为日期,默认为每个月的第一天:
select value, to_date(case when length(value) = 4 then '19' else '20' end
|| lpad(value, 4, '0'), 'YYYYMM') as dt
from t
order by to_date(case when length(value) = 4 then '19' else '20' end
|| lpad(value, 4, '0'), 'YYYYMM');
VALUE DT
---------- ----------
9909 1999-09-01
9912 1999-12-01
6 2000-06-01
9 2000-09-01
12 2000-12-01
103 2001-03-01
如果您只查看 1950-2049 年 Y2K 安全范围内的日期,您可以跳过世纪部分并改用 RR 日期模型,不过因为这可能会在以后给您带来问题,所以没有'与使用长度前缀世纪相比,确实没有任何优势:
select value, to_date(lpad(value, 4, '0'), 'RRMM') as dt
from t
order by to_date(lpad(value, 4, '0'), 'RRMM');
VALUE DT
---------- ----------
9909 1999-09-01
9912 1999-12-01
6 2000-06-01
9 2000-09-01
12 2000-12-01
103 2001-03-01
我需要对日期值为数字格式的 varchar2 数据类型列进行排序,格式为 YYMM
到 MMYY
取值范围为
3
6
9
12
103
.
.
9909
9912
长度为4个字符的值表示1900到1999之间的年份 少于4个字符表示年份以2000年及以上开始。
我尝试使用 LPAD(fieldname, 4,'0'),其中 returns 值为
0003 this is nothing but 2000/03
0006 ------------------- 2000/06
0009
0012
0103 ------------------- 2001/03
.
.
9912 ------------------- 1999/12
如何根据从 1900 年开始的年份值按升序对列进行排序。 谁能给我解决方案....
您需要先区分现有的四位数字值,以便在填充其余部分之前知道它们是 20 世纪的日期。
然后将其转换为日期和 fiddle 格式以获得您需要的排序顺序:
select to_char( expanded_dt, 'MMYYYY') as switched_dt
from (
select to_date(
case when length(dt) = 4 then '19'||dt
else '20'||lpad(dt,4,'0') end
, 'YYYYMM' )
as expanded_dt
from your_table
)
order by 1 asc
/
首先,将 DATE 值存储为 VARCHAR2 并仅使用 部分元素。在漫长的运行中,你应该首先修复你的设计。
作为解决方法,如果年份值在 1950-2049
范围内,您可以使用 RR
格式作为 两位数字年.
TO_DATE(LPAD(date_column, 4,'0'), 'RRMM')
LPAD
将添加所需的前导零。
例如,
SQL> alter session set nls_date_format='MM/DD/YYYY';
Session altered.
SQL> WITH dates AS(
2 SELECT '3' dt FROM dual UNION ALL
3 SELECT '6' dt FROM dual UNION ALL
4 SELECT '9' dt FROM dual UNION ALL
5 SELECT '12' dt FROM dual UNION ALL
6 SELECT '103' dt FROM dual UNION ALL
7 SELECT '9909' dt FROM dual UNION ALL
8 SELECT '9912' dt FROM dual
9 )
10 SELECT dt,
11 TO_DATE(LPAD(dt, 4,'0'), 'RRMM') date_val
12 FROM dates
13 ORDER BY date_val;
DT DATE_VAL
---- ----------
9909 09/01/1999
9912 12/01/1999
3 03/01/2000
6 06/01/2000
9 09/01/2000
12 12/01/2000
103 03/01/2001
7 rows selected.
SQL>
因此,上面的查询为您提供了所需的输出,日期值现在按升序排序。
您可以根据值的长度添加一个世纪标记:
select value,
case when length(value) = 4 then '19' else '20' end || lpad(value, 4, '0') as dt
from t
order by case when length(value) = 4 then '19' else '20' end || lpad(value, 4, '0');
VALUE DT
---------- ------
9909 199909
9912 199912
6 200006
9 200009
12 200012
103 200103
或者使用相同的东西并转换为日期,默认为每个月的第一天:
select value, to_date(case when length(value) = 4 then '19' else '20' end
|| lpad(value, 4, '0'), 'YYYYMM') as dt
from t
order by to_date(case when length(value) = 4 then '19' else '20' end
|| lpad(value, 4, '0'), 'YYYYMM');
VALUE DT
---------- ----------
9909 1999-09-01
9912 1999-12-01
6 2000-06-01
9 2000-09-01
12 2000-12-01
103 2001-03-01
如果您只查看 1950-2049 年 Y2K 安全范围内的日期,您可以跳过世纪部分并改用 RR 日期模型,不过因为这可能会在以后给您带来问题,所以没有'与使用长度前缀世纪相比,确实没有任何优势:
select value, to_date(lpad(value, 4, '0'), 'RRMM') as dt
from t
order by to_date(lpad(value, 4, '0'), 'RRMM');
VALUE DT
---------- ----------
9909 1999-09-01
9912 1999-12-01
6 2000-06-01
9 2000-09-01
12 2000-12-01
103 2001-03-01