iT邦幫忙

DAY 20
3

哇咧~夠了(Oracle SQL)系列 第 17

廿、分秒必爭?(Oracle SQL 2013/10/05)

  • 分享至 

  • xImage
  •  

話說鐵人賽每到晚上11點過後,如果還沒想到今天的發文內容,那真的是分秒必爭,
就來舉個"分秒必爭嗎?"的話題吧!

每天刷卡上下班,如何找出遲到10分鐘內的名單
例如: 8點上班,8:01:00 - 8:10:59算遲到,之後的一律請假
網路看到很多在寫這類條件的問答,很多都是這麼寫的

where card_datetime >= to_date('2013/10/05 08:01:00', 'yyyy/mm/dd hh24:mi:ss')
    and card_datetime <= to_date('2013/10/05 08:09:59', 'yyyy/mm/dd hh24:mi:ss')

來測試看看

create table ithelp_cards
 (card_no        number,
  card_datetime  date);

insert into  ithelp_cards values(10001, to_date('20131005 080059', 'yyyymmdd hh24miss'))
....

檢查資料
select card_no, to_char(card_datetime, 'yyyy/mm/dd hh24:mi:ss') card_datetime
from ithelp_cards

共4筆
  CARD_NO CARD_DATETIME
--------- -----------------------------------------------------------
    10001 2013/10/05 08:00:59
    10002 2013/10/05 08:01:00
    10003 2013/10/05 08:09:59
    10004 2013/10/05 08:10:00

select card_no, to_char(card_datetime, 'yyyy/mm/dd hh24:mi:ss') card_datetime
  from ithelp_cards
 where card_datetime >= to_date('2013/10/05 08:01:00', 'yyyy/mm/dd hh24:mi:ss')
   and card_datetime <= to_date('2013/10/05 08:09:59', 'yyyy/mm/dd hh24:mi:ss')

結果沒錯
  CARD_NO CARD_DATETIME
--------- -------------------------------------------------------
    10002 2013/10/05 08:01:00
    10003 2013/10/05 08:09:59

那,當你要抓的是整個月呢?
再補兩筆來測試
CARD_NO CARD_DATETIME


10001 2013/10/05 08:00:59
10002 2013/10/05 08:01:00
10003 2013/10/05 08:09:59
10004 2013/10/05 08:10:00
10001 2013/10/04 08:10:00
10002 2013/10/04 08:00:00

結果是這種單一日寫法變得無法處理了,必須改寫

 where card_datetime >= to_date('2013/10/01 08:01:00', 'yyyy/mm/dd hh24:mi:ss')
     and card_datetime <= to_date('2013/10/31 08:09:59', 'yyyy/mm/dd hh24:mi:ss')

那要寫多少條件?我不想用上面SQL改寫....

那試試這個做法吧!
先觀察資料,Date or datetime 在oracle都可以直接拿來加減的,
把她扣掉她自己的純日期,會得到刷卡時間的日數(0~1),trunc可不加’dd’,習慣補上

  1  select card_no
  2  ,      substrb(to_char(card_datetime, 'yyyy/mm/dd hh24:mi:ss'), 1, 25) card_datetime
  3  ,      card_datetime - trunc(card_datetime , 'dd') days
  4    from ithelp_cards
  5   where card_datetime >= to_date('2013/10/01', 'yyyy/mm/dd')
  6     and card_datetime <= to_date('2013/10/31', 'yyyy/mm/dd')
  7*    and card_datetime - trunc(card_datetime , 'dd') > 0

  CARD_NO CARD_DATETIME                  DAYS
--------- ------------------------- ---------
    10001 2013/10/05 08:00:59        .3340162
    10002 2013/10/05 08:01:00       .33402778
    10003 2013/10/05 08:09:59        .3402662
    10004 2013/10/05 08:10:00       .34027778
    10001 2013/10/04 08:10:00       .34027778
    10002 2013/10/04 08:00:00       .33333333

發現兩個門檻,分別是
08:01:00 .33402778
08:09:59 .3402662

所以加上這個門檻,因為日數算到1秒,會有很多小數位後看不到被進位的小差異,會影響結果,
可斟酌進位到5位小數即可。

  1  select card_no
  2  ,      substrb(to_char(card_datetime, 'yyyy/mm/dd hh24:mi:ss'), 1, 25) card_datetime
  3  ,      card_datetime - trunc(card_datetime, 'dd')  days
  4    from ithelp_cards
  5   where card_datetime >= to_date('2013/10/01', 'yyyy/mm/dd')
  6     and card_datetime <= to_date('2013/10/31', 'yyyy/mm/dd')
  7     and card_datetime - trunc(card_datetime , 'dd') >  0.33402
  8*    and card_datetime - trunc(card_datetime , 'dd') <  0.34027

  CARD_NO CARD_DATETIME                  DAYS
--------- ------------------------- ---------
    10002 2013/10/05 08:01:00       .33402778
    10003 2013/10/05 08:09:59        .3402662

另外,小時差可以直接用 1/24 ~ 2/24 方式表示1點到2點,
包含上述條件,也可以用 (8*60*60 sec + 1*60 sec) / 86400 sec
= 0.3340277777777778 天

這兩句就會變成這樣

and card_datetime - trunc(card_datetime , 'dd') > (8*6*60 +   1*60 + 0)/86400 --8:01:00
and card_datetime - trunc(card_datetime , 'dd') < (8*6*60 + 10*60 + 0)/86400 --8:10:00  

雖然俗話說:要怎麼收穫就怎麼栽...
但我還是那句話,看到"那種"條件未必要用"那種"方式解答,僅供參考!

[開發技術組]全文閱讀
http://ithelp.ithome.com.tw/ironman6/player/yafuu168/dev/1

[鐵人人生組]全文閱讀
http://ithelp.ithome.com.tw/ironman6/player/yafuu168/life/1


上一篇
十九、比較的簡單級,簡單事不要複雜處理(Oracle SQL 2013/10/04)
下一篇
廿一、用SQL Plus 設計個小遊戲之1((Oracle SQL 2013/10/06)
系列文
哇咧~夠了(Oracle SQL)28
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
月半車甫
iT邦研究生 3 級 ‧ 2013-10-05 11:51:47

終於邁向倒數10天,很辛苦的自己挑戰,
後面有時間的話,想做一隻小遊戲,時間不夠,就等完結後再來POST。
加油!

我要留言

立即登入留言