【问题标题】:Order by Date not functioning as expected按日期排序未按预期运行
【发布时间】:2019-09-26 13:54:18
【问题描述】:

我正在编写一个按日期报告活动信息的 PL/SQL 过程。我在原始日期(类型为日期)字段上排序的地方似乎没有正确排序。如果我使用 to_char 转换它,它可以工作;但 to_char 可能有自己的问题。为什么会这样?

我已经在数据库字段 PT.BEGIN_DATE 上尝试了 order by,并使用下面显示的 to_char 进行了尝试。

select  PT.BEGIN_DATE, PT.TRAN_TYPE || '/' || PT.TRAN_CODE as TRAN,
   PT.TRAN_NBR, PT.MODULE_NAME, PT.MENU_OPTN_NAME,  
   TO_CHAR(EXTRACT(HOUR FROM NUMTODSINTERVAL(PT.END_DATE - PT.BEGIN_DATE, 'DAY')), 'FM00') || ':' ||
  TO_CHAR(EXTRACT(MINUTE FROM NUMTODSINTERVAL(PT.END_DATE - PT.BEGIN_DATE, 'DAY')), 'FM00') || ':' ||
  TO_CHAR(EXTRACT(SECOND FROM NUMTODSINTERVAL(PT.END_DATE - PT.BEGIN_DATE, 'DAY')), 'FM00') as Elapsed,
  SU.USER_NAME, COALESCE(trim(IM.SKU_BRCD), ' '), COALESCE(trim(PT.CNTR_NBR),'  '), COALESCE(trim(PT.WAVE_NBR), ' '), COALESCE(trim(PT.PKT_CTRL_NBR), ' '), COALESCE(trim(PT.PKT_SEQ_NBR), ' '), 
  PT.NBR_UNITS, COALESCE(trim(LH1.LOCN_BRCD), ' ') as FROM_LOCN, COALESCE(trim(LH2.LOCN_BRCD), ' ') as TO_LOCN, COALESCE(trim(PT.OLD_STAT_CODE), ' '), COALESCE(trim(PT.NEW_STAT_CODE), ' '), 
  COALESCE(trim(PT.WKSTN_ID), ' '), PT.USER_ID, PT.END_DATE
from ACT_TRACK_TRAN PT
   left join SKU_MASTER IM on IM.SKU_ID = PT.SKU_ID
   left join LOCN_MASTER LH1 on LH1.LOCN_ID = PT.FROM_LOCN
   left join LOCN_MASTER LH2 on LH2.LOCN_ID = PT.TO_LOCN
   left join SEC_USER SU on SU.LOGIN_USER_ID = PT.USER_ID
   where pt.MASTER_ID = v_CD and PT.SKU_ID like v_SKUID and PT.USER_ID   
like v_USER and PT.PKT_CTRL_NBR like v_PKT and PT.CNTR_NBR Like v_CNTR 
   and trunc(PT.BEGIN_DATE) between trunc(v_START) and trunc(v_STOP)
   ORDER BY to_char(PT.BEGIN_DATE, 'yyyymmddhhmmss') ;

结果如上图:

Start Date/Time    
------------------- 
09/09/2019 10:09:09 
09/09/2019 10:09:23 
09/09/2019 10:09:27

仅在 PT_BEGIN_DATE 排序时的结果

Start Date/Time     
------------------- 
09/09/2019 10:09:23 
09/09/2019 10:09:09 
09/09/2019 10:09:27

【问题讨论】:

  • 只使用ORDER BY PT.BEGIN_DATE,它的类型是date,不是吗? (你为什么要转换成字符串?
  • 我试过了,结果如上图错误
  • 试试ORDER BY to_char(PT.BEGIN_DATE, 'yyyymmddhh24mmss') 或者更简单的ORDER BY PT.BEGIN_DATE。为什么使用TO_CHAR
  • REGEXP_SUBSTR(NUMTODSINTERVAL(PT.END_DATE - PT.BEGIN_DATE, 'DAY'), '\d{2}:\d{2}:\d{2}') as Elapsed 会更短。
  • 感谢大家的帮助,但我必须将此来源发送回密码柜进行审核。所以我暂时保持原样。

标签: sql oracle sql-order-by


【解决方案1】:

在您发布的 order-by 子句中,您使用模型 'yyyymmddhhmmss' 将日期转换为字符串。那就是使用月份两次 - 它应该是 'yyyymmddhhmiss'mi 表示分钟,而不是 mm,这是月份);或者最好是'yyyymmddhh24miss' 以避免上午/下午的混淆。 (这里没有理由转换为字符串进行排序,但我认为您这样做只是为了调查为什么它在纯日期时出现错误......)

由于您显示的输出与您声明的 NLS 设置不匹配,您必须将查询结果转换为其他地方的字符串。大概你在格式模型中也犯了同样的错误。

因此,当您仅按日期值(如您所应)而不是按其字符串表示进行排序时,结果实际上是正确的顺序;但是因为您后来也显示了错误的分钟值,所以它只是似乎是错误的。

带有两种订购选项的快速演示:

with pt (begin_date) as (
  select to_date('2019-09-09 10:01:23', 'YYYY-MM-DD HH24:MI:SS') from dual
  union all
  select to_date('2019-09-09 10:02:09', 'YYYY-MM-DD HH24:MI:SS') from dual
  union all
  select to_date('2019-09-09 10:03:27', 'YYYY-MM-DD HH24:MI:SS') from dual
)
select begin_date,
  to_char(begin_date, 'yyyymmddhhmmss') as wrong_1,
  to_char(begin_date, 'mm/dd/yyyy hh:mm:ss') as wrong_2,
  to_char(begin_date, 'mm/dd/yyyy hh24:mi:ss') as right_3
from pt
order by begin_date;

BEGIN_DATE          WRONG_1        WRONG_2             RIGHT_3            
------------------- -------------- ------------------- -------------------
2019-09-09 10:01:23 20190909100923 09/09/2019 10:09:23 09/09/2019 10:01:23
2019-09-09 10:02:09 20190909100909 09/09/2019 10:09:09 09/09/2019 10:02:09
2019-09-09 10:03:27 20190909100927 09/09/2019 10:09:27 09/09/2019 10:03:27

当按普通日期排序时,wrong_2 值的顺序似乎是错误的,但 right_3 显示的顺序实际上是正确的。

with ...
select begin_date,
  to_char(begin_date, 'yyyymmddhhmmss') as wrong_1,
  to_char(begin_date, 'mm/dd/yyyy hh:mm:ss') as wrong_2,
  to_char(begin_date, 'mm/dd/yyyy hh24:mi:ss') as right_3
from pt
order by to_char(begin_date, 'yyyymmddhhmmss');

BEGIN_DATE          WRONG_1        WRONG_2             RIGHT_3            
------------------- -------------- ------------------- -------------------
2019-09-09 10:02:09 20190909100909 09/09/2019 10:09:09 09/09/2019 10:02:09
2019-09-09 10:01:23 20190909100923 09/09/2019 10:09:23 09/09/2019 10:01:23
2019-09-09 10:03:27 20190909100927 09/09/2019 10:09:27 09/09/2019 10:03:27

当按(不正确的)字符串排序时,wrong_2 值的顺序似乎正确,但 right_3 显示的顺序实际上是错误的。

【讨论】:

  • 就是这样。我太专注于订单了,我什至没有看那个。谢谢
  • 完美解释!!向你兄弟致敬!!
  • @DocMac - 如果这确实是您发布的问题的正确答案,请不要忘记相应地标记它。
【解决方案2】:

在排序之前转换为日期。 ORDER BY CONVERT(DATE, PT.BEGIN_DATE) ASC

【讨论】:

  • 这不是 Oracle 语法。从日期转换为字符串,然后再转换回日期是没有意义的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-12-10
  • 2018-02-27
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-06
相关资源
最近更新 更多