在Oracle SQL中排除/忽略周末

时间:2015-06-15 11:22:01

标签: sql oracle

我做了一个查询,将文本组合在一起以及它们的开始和结束日期,我想排除/忽略周末。

在这个例子中,11-12和18-19是周末

 create table t ( d date, v varchar2(10));
    insert into t values (date '2015-04-10', 'ne');
    insert into t values (date '2015-04-13', 'ne');
    insert into t values (date '2015-04-14', 'jm');
    insert into t values (date '2015-04-15', 'ne');
    insert into t values (date '2015-04-16', 'jm');
    insert into t values (date '2015-04-17', 'jm');
    insert into t values (date '2015-04-20', 'jm');
    insert into t values (date '2015-04-21', 'jm');

和查询

select min(d), max(d), v
from (
    select d, v, 
        sum( gc) over (partition by v order by d) g
    from (
        select d, v, 
            (case (d - lag(d) over ( partition by v order by d) )
                when 1 then 0
                else 1
             end) gc
        from t
    )
) group by v, g
order by min(d), v

我做了一个SQLFiddle http://sqlfiddle.com/#!4/662918/1

输出

MIN(D)           max(D)           v
2015-04-10 - 2015-04-13 - ne
2015-04-14 - 2015-04-14 - jm
2015-04-15 - 2015-04-15 - ne
2015-04-16 - 2015-04-21 - jm

2 个答案:

答案 0 :(得分:2)

您的查询在case ... when中进行了少量修改,不包括周末日期:

select min(d), max(d), v
  from (
    select d, v, sum( gc) over (partition by v order by d) g
      from (
        select d, v, 
            case when d-lag(d) over (partition by v order by d) 
                          = decode(trunc(d, 'iw') - d, 0, 3, 1)
                 then 0
                 else 1
            end gc
          from t)) 
  group by v, g
  order by min(d), v

SQLFiddle

递归解决方案也是可行的,但我怀疑这更快。

答案 1 :(得分:1)

您可以添加以下过滤器:

WHERE TO_CHAR(d, 'DY','NLS_DATE_LANGUAGE=AMERICAN') NOT IN ('SAT', 'SUN')

例如,

<强>设置

CREATE TABLE t ( d DATE, v VARCHAR2(10));
    INSERT INTO t VALUES (DATE '2015-04-10', 'ne');
    INSERT INTO t VALUES (DATE '2015-04-11', 'ne'); --> Added new row for demo
    insert into t values (date '2015-04-12', 'ne'); --> Added new row for demo
    INSERT INTO t VALUES (DATE '2015-04-13', 'ne');
    INSERT INTO t VALUES (DATE '2015-04-14', 'jm');
    INSERT INTO t VALUES (DATE '2015-04-15', 'ne');
    INSERT INTO t VALUES (DATE '2015-04-16', 'jm');
    INSERT INTO t VALUES (DATE '2015-04-17', 'jm');
    INSERT INTO t VALUES (DATE '2015-04-18', 'jm'); --> Added new row for demo
    INSERT INTO t VALUES (DATE '2015-04-19', 'jm'); --> Added new row for demo
    INSERT INTO t VALUES (DATE '2015-04-20', 'jm');
    INSERT INTO t VALUES (DATE '2015-04-21', 'jm');

SQL> SELECT * FROM t;

D         V
--------- ----------
10-APR-15 ne
11-APR-15 ne
12-APR-15 ne
13-APR-15 ne
14-APR-15 jm
15-APR-15 ne
16-APR-15 jm
17-APR-15 jm
18-APR-15 jm
19-APR-15 jm
20-APR-15 jm

D         V
--------- ----------
21-APR-15 jm

12 rows selected.

测试用例

SQL> SELECT *
  2  FROM t
  3  WHERE TO_CHAR(d, 'DY','NLS_DATE_LANGUAGE=AMERICAN') NOT IN ('SAT', 'SUN');

D         V
--------- ----------
10-APR-15 ne
13-APR-15 ne
14-APR-15 jm
15-APR-15 ne
16-APR-15 jm
17-APR-15 jm
20-APR-15 jm
21-APR-15 jm

8 rows selected.

因此,在查询中使用上述逻辑可以获得所需的输出。

修改后的查询

SQL> SELECT MIN(d),
  2    MAX(d),
  3    v
  4  FROM
  5    (SELECT d,
  6      v,
  7      SUM( gc) over (partition BY v order by d) g
  8    FROM
  9      (SELECT d,
 10        v,
 11        (
 12        CASE (d - lag(d) over ( partition BY v order by d) )
 13          WHEN 1
 14          THEN 0
 15          ELSE 1
 16        END) gc
 17      FROM t
 18      )
 19    )
 20  WHERE TO_CHAR(d, 'DY','NLS_DATE_LANGUAGE=AMERICAN') NOT IN ('SAT', 'SUN')
 21  GROUP BY v,
 22    g
 23  ORDER BY MIN(d),
 24    v;

MIN(D)    MAX(D)    V
--------- --------- ----------
10-APR-15 13-APR-15 ne
14-APR-15 14-APR-15 jm
15-APR-15 15-APR-15 ne
16-APR-15 21-APR-15 jm

SQL>