Narisa.com: นับวันทำงาน และ วันหยุด - Narisa.com

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

นับวันทำงาน และ วันหยุด

#1 User is offline   ekkapong 

  • Member
  • PipPip
  • Group: Members
  • Posts: 325
  • Joined: 19-February 05

Posted 03 December 2009 - 03:58 PM

รบกวนถามว่า ถ้าผมมี field รับค่าวันที่ 2 field ( form 6i ) คือ start_date และ end_date พอรับค่าเข้าไปเช่น
start_date = 01/01/2551
end_date = 31/01/2551

ผมอยากทราบว่า 1..มีวันที่เป็นวันทำงาน คือ จันทร์ ถึง ศุกร์ กี่วัน
2..วันหยุด คือ เสาร์ และ อาทิตย์ กี่วัน
ในช่วง start_date ถึง end_date

condition มีเพียงเท่านี้ครับ ไม่ทราบว่าท่านใดพอมีแนวทาง หรือตัวอย่าง บ้างครับ

ขอบคุณมากครับ
0

#2 User is offline   JoeIMIsu 

  • Member
  • PipPip
  • Group: Members
  • Posts: 134
  • Joined: 05-August 08

Posted 04 December 2009 - 10:18 AM

SELECT COUNT(DAY) FROM (
SELECT TO_CHAR(TO_DATE('01/12/2009','dd/mm/yyyy') + (LEVEL-1),'day') DAY
FROM dual CONNECT BY LEVEL <= SUBSTR(LAST_DAY(TO_DATE('01/12/2009','dd/mm/yyyy')),1,2)
)
WHERE trim(DAY) IN('saturday','sunday')

อันนี้ คิดในหนึ่งเดือนอ่ะครับ count วันเสาร์กับวันอาทิตย์ครับค่อยเอาไปลบกับจำนวนวันจริงเอาครับ
ถ้ามากกว่านั้นก็เอาวันที่มาลบกันแล้วเอาไปใส่แทนตรง SUBSTR(LAST_DAY(TO_DATE('01/12/2009','dd/mm/yyyy')),1,2)

ส่วนโค้ดผมอะแดปมาจากของพี่ siamnobita จากกระทู้ที่ถามเรื่องเวลาไรนี้ล่ะครับ
ผมก็ไม่ค่อยรู้เรื่องเหมือนกันครับ ฮ่าๆ

SELECT TO_CHAR( TRUNC ( SYSDATE) + (LEVEL-1)/24/60,'HH24.MI') FROM dual CONNECT BY LEVEL <= 24*60


รอท่านอื่นมาต่อครับ
ปล. oracle 10g คับ
0

#3 User is offline   ekkapong 

  • Member
  • PipPip
  • Group: Members
  • Posts: 325
  • Joined: 19-February 05

Posted 04 December 2009 - 11:53 AM

ได้แล้วครับ :lol: และขอบคุณ คุณ JoeIMIsu ด้วยครับ
สร้างเป็น function ไว้นะครับ

CREATE OR REPLACE FUNCTION daysbetween
  (dateFrom in date, dateTo in date)
return number
IS
begin
declare
	  days number;
begin
		days := dateTo-dateFrom+1;
		for i in 0 .. days-1 loop
			  -- In my locale, the week starts Sun so Sun = 1, Sat = 7
			  if to_char(dateFrom+i, 'd') in (1, 7) then
					  days := days - 1;
			end if;					  
		end loop;
		return days;
end;
end;


ลอง query ดู select daysbetween('01/01/2552','11/01/2552') from dual;
0

#4 User is offline   OopWow 

  • Member
  • PipPip
  • Group: Members
  • Posts: 145
  • Joined: 16-January 08

Posted 21 December 2009 - 04:36 PM

SELECT COUNT (*)
  FROM (SELECT TO_CHAR (calendars.days,
                        'D',
                        'nls_date_language=american'
                       ) abbrv,
               DECODE (TO_CHAR (calendars.days,
                                'D',
                                'nls_date_language=american'
                               ),
                       '1', 'W',
                       '7', 'W',
                       'B'
                      ) dow,
               days
          FROM (SELECT       TRUNC
                                (ADD_MONTHS
                                    (LAST_DAY
                                        (fnd_date.canonical_to_date
                                                                  (:start_date)
                                        ),
                                     -1
                                    )
                                )
                           + LEVEL days
                      FROM DUAL
                CONNECT BY LEVEL <=
                                (  TRUNC
                                      (LAST_DAY
                                          (fnd_date.canonical_to_date
                                                                    (:end_date)
                                          )
                                      )
                                 - TRUNC
                                      (fnd_date.canonical_to_date (:start_date),
                                       'MONTH'
                                      )
                                )
                              + 1) calendars) calen1
 WHERE calen1.dow = 'W'


concept เดียวกันกับ function ครับ แต่เขียนเป็น SQL
0

#5 User is offline   siamnobi 

  • Topgun
  • View blog
  • Group: Topgun
  • Posts: 444
  • Joined: 05-April 04

Posted 29 December 2009 - 10:38 AM

ลองคิดเล่น ๆ ว่าถ้าใช้ built-in function ล้วน ๆ จะทำได้ไหม ผลออกมาอย่างที่เห็นครับ

SQL> select d1, d2
  2	, greatest((next_day(d1,7)-d1)-5,0)
  3	+ ((next_day(d2,7)-7)-next_day(d1,7))/7*2
  4	+ least ((d2+1) - (next_day(d2,7)-7),2)
  5	as cnt
  6  from weekend_count
  7  /

D1				  D2						 CNT
------------------- ------------------- ----------
01/12/2009 00:00:00 31/12/2009 00:00:00		  8
05/12/2009 00:00:00 05/12/2009 00:00:00		  1
05/12/2009 00:00:00 06/12/2009 00:00:00		  2
05/12/2009 00:00:00 12/12/2009 00:00:00		  3
07/12/2009 00:00:00 11/12/2009 00:00:00		  0
01/01/2010 00:00:00 31/01/2010 00:00:00		 10

6 rows selected.


หลักการคือ หาวันเสาร์แรก และ เสาร์สุดท้ายในช่วงมาโดยใช้ฟังก์ชั่น next_day(d1,7) และ next_day(d2,7)-7
นับ weekend ช่วงที่หนึ่งคือ ตั้งแต่วันแรกจนถึงวันเสาร์แรก จะมีเสาร์อาทิตย์เท่ากับจำนวนวันที่เกิน 5 วัน
นับ weekend ช่วงที่สองคือ ตั้งแต่วันเสาร์แรกจนถึงวันเสาร์สุดท้าย จะมีเสาร์อาทิตย์เท่ากับจำนวนวันหารเจ็ดคูณสอง
นับ weekend ช่วงที่สามคือ ตั้งแต่วันเสาร์สุดท้ายจนถึงวันสุดท้าย จะมีเสาร์อาทิตย์เท่ากับจำนวนวัน แต่ไม่เกินสอง

จริง ๆ logic นี้ อาจมีจุดอ่อนในกรณีที่ ช่วงวันที่ยาวไม่พอที่จะแบ่งเป็นสามช่วงได้ แต่เท่าที่ทดสอบดูหลาย ๆ เคส
พบว่าจำนวนวันจากช่วงที่สองจะติดลบ และชดเชยกันจนได้ผลลัพธ์ที่ถูกต้องอยู่ดี ถ้าใครลองทดสอบดูแล้วเจอเคส
ที่ใช้ไม่ได้ รบกวนแจ้งด้วยนะครับ ขอบคุณครับ

This post has been edited by siamnobi: 29 December 2009 - 10:43 AM

0

#6 User is offline   ekkapong 

  • Member
  • PipPip
  • Group: Members
  • Posts: 325
  • Joined: 19-February 05

Posted 04 January 2010 - 02:07 PM

เยี่ยมเลยครับ นี่ขนาดนั่งคิดเล่นๆนะเนี่ยะ

This post has been edited by ekkapong: 08 January 2010 - 01:30 PM

0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users