如何在两个日期之间排除假期?

时间:2013-06-18 08:07:17

标签: oracle date datetime oracle-sqldeveloper

我有两个约会,我必须知道这两个日期之间的星期日和假日数量。我可以使用BETWEEN吗?如果是这样,怎么样?

SELECT date1, date2, trunc(deposit_date - transaction_date) TOTAL
FROM Table_Name FULL OUTER JOIN Holidays ON date2 = hdate
WHERE hdate IN (date1, date2)

使用这个我绝对可以检查这两天中的任何一天是否有假期,即date1或date2,但我无法知道这两个日期之间是否有假期或星期日。救命啊!

7 个答案:

答案 0 :(得分:3)

您发布的解决方案非常低效;你可以在一个SQL语句中完成所有这些:

首先在两者之间生成所有可能的日期:

 select trunc(:min_date) + level - 1
   from dual
connect by level <= trunc(:min_date) - trunc(:max_date)

然后使用您的HOLIDAY表限制您想要的内容:

with all_dates as (
 select trunc(:min_date) + level - 1 as the_date
   from dual
connect by level <= trunc(:min_date) - trunc(:max_date)
        )
select count(*)
  from all_dates a
  left outer join holiday b
    on a.the_date = b.hdate
 where b.hdate is null
   and to_char(a.the_date, 'DY') <> 'SUN'

答案 1 :(得分:1)

如果您想检查hdate是否在您可以使用

查询的两个日期之间
where hdate between date1 and date2

如果您想检查hdate是否与date1或date 2同一天,您可以像这样查询

where trunc(hdate) in (trunc(date1) ,trunc(date2))

trunc功能删除了时间。

答案 2 :(得分:1)

您应该创建一个包含假期的表格,并自行维护。

CREATE TABLE holidays
(
    holiday VARCHAR2(100)
,   d_date DATE
);

INSERT INTO holidays VALUES ('National Developer Day', DATE'2013-06-01');

SELECT  *
FROM    holidays;
-- National Developer Day   2013-06-01 00:00:00

其余的只是SQL语句的问题

场景1:EXISTS

SELECT  COUNT
        (
            CASE
                WHEN TRIM(TO_CHAR(d.start_date_level, 'DAY')) = 'SUNDAY'
                OR  CASE
                        WHEN EXISTS (SELECT 1 FROM holidays h WHERE d.start_date_level = h.d_date)
                        THEN 1
                        ELSE NULL
                    END = 1
                THEN    1
                ELSE    NULL
            END
        ) AS holiday_check
FROM
(
        SELECT  start_date + (LEVEL - 1) AS start_date_level
        FROM
        (
                SELECT  start_date, end_date, end_date - start_date AS diff_date
                FROM
                (
                        SELECT  TRUNC(ADD_MONTHS(SYSDATE, -2)) AS start_date
                        ,       TRUNC(SYSDATE)                 AS end_date
                        FROM    DUAL
                )
        ) 
        CONNECT BY
                LEVEL <= (diff_date + 1)
) d

场景2:LEFT JOIN

SELECT  COUNT
        (
            CASE
                WHEN TRIM(TO_CHAR(d.start_date_level, 'DAY')) = 'SUNDAY'
                OR   h.d_date IS NOT NULL
                THEN 1
                ELSE NULL
            END
        ) AS holiday_check
FROM
(
        SELECT  start_date + (LEVEL - 1) AS start_date_level
        FROM
        (
                SELECT  start_date, end_date, end_date - start_date AS diff_date
                FROM
                (
                        SELECT  TRUNC(ADD_MONTHS(SYSDATE, -2)) AS start_date
                        ,       TRUNC(SYSDATE)                 AS end_date
                        FROM    DUAL
                )
        ) 
        CONNECT BY
                LEVEL <= (diff_date + 1)
) d
LEFT    JOIN holidays h
ON      d.start_date_level = h.d_date

9个星期日+ 1&#34;国家开发者日&#34; = 10

答案 3 :(得分:0)

CREATE OR REPLACE FUNCTION workdays (dt1 DATE, dt2 DATE) RETURN NUMBER IS
weekday_count NUMBER := 0;
date1 DATE := dt1;
date2 DATE := dt2;
cur_dt date;
holiday_count number;
begin
if date1 = date2 then
    return 0;
end if;
cur_dt := transaction_date;
while cur_dt <= date2 loop
    if cur_dt = date2 then 
        null;
    else
        SELECT count(*) INTO holiday_count 
        FROM holiday
         WHERE hdate = cur_dt;
        IF holiday_count = 0 THEN
            IF to_char(cur_dt,'DY') NOT IN ('SUN') THEN
                weekday_count := weekday_count + 1;
            END IF;
        END IF;
    END IF;
    cur_dt := cur_dt +1;
END LOOP;
RETURN weekday_count;
END;

然后我查询了我的数据库并得到了正确的结果。如果您有最佳解决方案,请发布。

答案 4 :(得分:0)

这是一个更好,更有效的问题解决方案,

SELECT A.ID,
COUNT(A.ID) AS COUNTED
FROM tableA A
LEFT JOIN TableB B
ON A.tableB_id=B.id
LEFT JOIN holiday C
ON TRUNC(C.hdate) BETWEEN (TRUNC(a.date1) +1) AND TRUNC(B.date2)
WHERE c.hdate IS NOT NULL
GROUP BY A.ID;

其中TableA包含date1,tableB包含date2。假日包含假日和星期日的列表。此查询从计数中排除'date1'。

结果逻辑

trunc(date2) - trunc(date1) = x      
x - result of the query

答案 5 :(得分:0)

用假期制作一张桌子T $ HOLIDAYS(HDATE专栏)。这些日期将被排除在给定期间内的工作日计算之外(sdate是开始日期和edate结束日期)。以下是计算给定时期内工作日的功能,不包括节假日,周六和周日:

CREATE OR REPLACE FUNCTION WorkingDays(sdate IN DATE,edate IN DATE) RETURN NUMBER IS
  days NUMBER;
BEGIN
  WITH dates AS (SELECT sdate+LEVEL-1 AS d FROM DUAL CONNECT BY LEVEL<=edate-sdate+1)
  SELECT COUNT(*) INTO days
  FROM dates
 WHERE d NOT IN (SELECT hdate FROM t$holidays) --exclude holidays
   AND TO_CHAR(d,'D') NOT IN (6,7); --exclude saturdays + sundays
  RETURN days;
END WorkingDays;
/

答案 6 :(得分:0)

select sum(qq) from (
 select case when to_number(to_char((trunc(sysdate-10) + level - 1),'D'))<=5 then 1 else 0 end as qq
   from dual
connect by level <= trunc(sysdate) - trunc(sysdate-10))