अगर मैं सही ढंग से समझूं, तो आप सुबह 10 बजे से पहले और शाम 7 बजे के बाद के समय को छोड़कर प्रारंभ और समाप्ति तिथि के बीच के अंतर की गणना करना चाहते हैं।
यहाँ नमूना क्वेरी और sql fiddle है।
SELECT start_time,
finish_time,
interval_time,
EXTRACT (HOUR FROM interval_time), --extract the hours,mins and seconds from the interval
EXTRACT (MINUTE FROM interval_time),
EXTRACT (SECOND FROM interval_time)
FROM (SELECT start_time,
finish_time,
NUMTODSINTERVAL (
CASE
WHEN finish_time - TRUNC (finish_time) > (19 / 24) --if finish time is after 7pm
THEN
TRUNC (finish_time) + (19 / 24) --set it to 7pm
ELSE
finish_time --else set it to actual finish time
END
- CASE
WHEN start_time - TRUNC (start_time) < (10 / 24) --if start time is before 10 am
THEN
TRUNC (start_time) + (10 / 24) --set it to 10 am.
ELSE
start_time --else set it to the actual start time
END,
'day') --subtract the both and convert the resulting day to interval
interval_time
FROM timings);
मैंने जो किया है वह है,
- जांचें कि क्या शुरू होने का समय सुबह 10 बजे से पहले है और खत्म होने का समय शाम 7 बजे के बाद है। यदि हां, तो समय सुबह 10 बजे और शाम 7 बजे निर्धारित करें।
- फिर तिथियों को घटाएं और परिणामी दिनों को अंतराल प्रकार में बदलें।
- फिर अंतराल से घंटे, मिनट और सेकंड निकालें।
नोट: यह प्रश्न मानता है कि दोनों तिथियां एक ही दिन पड़ती हैं और दोनों सुबह 10 बजे से पहले या शाम 7 बजे के बाद नहीं होती हैं।
अपडेट करें: छुट्टियों को बाहर करने के लिए, क्वेरी जटिल हो जाएगी। मेरा सुझाव है कि तीन फ़ंक्शन लिखें और क्वेरी में इन फ़ंक्शन का उपयोग करें।
पहला समारोह:
FUNCTION modify_start_time (p_in_dte DATE) RETURN DATE
----------------------------------
IF p_in_dte - TRUNC (p_in_dte) < (10 / 24)
THEN
RETURN TRUNC (p_in_dte) + (10 / 24);
ELSIF p_in_dte - TRUNC (p_in_dte) > (19 / 24)
THEN
RETURN TRUNC (p_in_dte) + 1 + (10 / 24);
ELSE
RETURN p_in_dte;
END IF;
यदि प्रारंभ समय कार्य घंटों के बाहर है, तो प्रारंभ समय को अगले निकटतम प्रारंभ समय में संशोधित करें।
दूसरा समारोह:
FUNCTION modify_finish_time (p_in_dte DATE) RETURN DATE
----------------------------------
IF p_in_dte - TRUNC (p_in_dte) > (19 / 24)
THEN
RETURN TRUNC (p_in_dte) + (19 / 24);
ELSIF p_in_dte - TRUNC (p_in_dte) < (10 / 24)
THEN
RETURN TRUNC (p_in_dte) - 1 + (19 / 24);
ELSE
RETURN p_in_dte;
END IF;
अगर काम खत्म करने का समय काम के घंटों से बाहर है, तो इसे पिछले निकटतम समाप्ति समय में संशोधित करें।
तीसरा समारोह:
FUNCTION get_days_to_exclude (p_in_start_date DATE,
p_in_finish_date DATE) RETURN NUMBER
--------------------------------------------------------
WITH cte --get all days between start and finish date
AS ( SELECT p_in_start_date + LEVEL - 1 dte
FROM DUAL
CONNECT BY LEVEL <= p_in_finish_date + 1 - p_in_starT_date)
SELECT COUNT (1) * 9 / 24 --mutiply the days with work hours in a day
INTO l_num_holidays
FROM cte
WHERE TO_CHAR (dte, 'dy') = 'sun' --find the count of sundays
OR dte IN --fins the count of holidays, assuming leaves are stored in separate table
(SELECT leave_date
FROM leaves
WHERE leave_date BETWEEN p_in_start_date
AND p_in_finish_date);
l_num_holidays :=
l_num_holidays + ( (p_in_finish_date - p_in_start_date) * (15 / 24)); --also, if the dates span more than a day find the non working hours.
RETURN l_num_holidays;
यह फ़ंक्शन अवधि की गणना करते समय बाहर किए जाने वाले दिनों की संख्या ढूंढता है।
तो, अंतिम क्वेरी कुछ इस तरह होनी चाहिए,
SELECT start_time,
finish_time,
CASE
WHEN work_duration < 0 THEN NUMTODSINTERVAL (0, 'day')
ELSE NUMTODSINTERVAL (work_duration, 'day')
END
FROM (SELECT start_time, finish_time,
--modify_start_time (start_time), modify_finish_time (finish_time),
modify_finish_time (finish_time)
- modify_start_time (start_time)
- get_days_to_exclude (
TRUNC (modify_start_time (start_time)),
TRUNC (modify_finish_time (finish_time)))
work_duration
FROM timings);
यदि अवधि 0 से कम है, तो इसे 0 पर सेट करके इसे अनदेखा करें।