1

我有两个日期,我必须找出这两个日期之间的星期日和节假日的数量。我可以使用 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 但我无法确定这两个日期之间是否有假期或星期日。帮助!

4

7 回答 7

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'
于 2013-06-18T11:58:11.740 回答
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:存在

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:左连接

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 个“全国开发者日”=10

于 2013-06-18T08:48:49.650 回答
1

如果要检查是否hdate在两个日期之间,可以使用查询

where hdate between date1 and date2

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

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

trunc功能删除了时间。

于 2013-06-18T08:24:30.117 回答
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;

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

于 2013-06-18T09:18:27.217 回答
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
于 2013-06-19T05:50:34.670 回答
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))
于 2018-06-05T06:51:36.077 回答
0

用您的假期(HDATE 列)制作一张 T$HOLIDAYS 表。这些日期将被排除在给定期间的工作日计算之外(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;
/
于 2017-02-22T11:44:23.307 回答