我可以使用下面的这个SELECT,将24小时的谬误排除在外并用00小时替换它,然后在TRUNC(SYSDATE-90)和TRUNC(SYSDATE)之间运行WHERE TRUNC(TO_DATE(FIX_DATETIME,'MMDDYYHH24MISS')) ?可以一次完成吗?如果是这样,无论是通过还是更多,怎么样?非常感谢您的帮助,并且您的技能水平得到尊重。
SELECT MOPACTIVITY.MOPID,
(CASE
WHEN SUBSTR(MOPACTIVITY.MOPID, 7, 2) = '24' THEN SUBSTR(MOPACTIVITY.MOPID, 1, 2)||SUBSTR(MOPACTIVITY.MOPID, 3, 2)||SUBSTR(MOPACTIVITY.MOPID, 5, 2)||'00'||SUBSTR(MOPACTIVITY.MOPID, 9, 2)||SUBSTR(MOPACTIVITY.MOPID, 11, 2)
ELSE MOPACTIVITY.MOPID
END ) FIX_DATETIME,
sysdate "SYSDATE"
FROM MOPUSER.MOPACTIVITY
答案 0 :(得分:6)
暂时搁置一个名为MOPID
的列的不协调,有人自然会认为它是某种数字ID,实际上是VARCHAR2
恰好代表DATE
和事实上你永远不应该将DATE
存储为VARCHAR2
,因为你不可避免地会在该列中找到无效数据,这会导致查询在查询计划发生变化时似乎随机地开始抛出错误......
WHERE to_date(MOPACTIVITY.MOPID, 'MMDDYYHH24MISS') BETWEEN (sysdate-90) and sysdate
会做你想要的。
识别具有无效数据的行(当您使用错误的数据类型时几乎可以确定)
CREATE OR REPLACE FUNCTION is_valid_date( p_str IN VARCHAR2,
p_mask IN VARCHAR2 )
RETURN VARCHAR2
IS
l_dt DATE;
BEGIN
l_dt := to_date( p_str, p_mask );
RETURN 'Y';
EXCEPTION
WHEN OTHERS THEN
RETURN 'N';
END;
然后
SELECT *
FROM MOPACTIVITY
WHERE is_valid_date( MOPID, 'MMDDYYHH24MISS' ) = 'N'
您可以尝试使用正则表达式或尝试使用SUBSTR
和INSTR
各种组件来查找无效数据。然而,这种方法只能是近似的,除非您想尝试实施每个可能的日历规则(即29-31是某些月份和有些年份的有效日期,而不是其他日期)。简单地让to_date
尝试转换并依靠Oracle来实现所有这些规则通常会更容易。
答案 1 :(得分:0)
如果您正在寻找 date 比较,您应该使用:
WHERE to_date(MOPACTIVITY.MOPID, 'MMDDYYHH24MISS') BETWEEN trunc(sysdate-90) and trunc(sysdate)
或
WHERE to_date(substr(MOPACTIVITY.MOPID, 1, 6), 'MMDDYY') BETWEEN trunc(sysdate-90) and trunc(sysdate)
这假定您需要完整的日期,包括当天(部分截至当前时间)和午夜的第一天(不是当前时间)。