在Oracle表中排除假期

时间:2015-06-11 09:23:28

标签: sql oracle

table1 K

Date          id
2015-01-01    10
2015-01-02    10
2015-01-03    10
2015-01-04    10
2015-01-05    10
2015-01-06    10

table2 H

Date          id   Holiday
2015-01-03    10   a holiday day 

我想从Date列中排除假期,并创建一个新列,如AS new_dates。 所以输出就像:

table3输出

new_dates     id
2015-01-01    10
2015-01-02    10
2015-01-04    10
2015-01-05    10
2015-01-06    10

4 个答案:

答案 0 :(得分:4)

现在已编辑。 根据MTO的回答,我建议EXCEPT ALL,但甲骨文有MINUS

select date, id from table1
MINUS
select date, id from table2

NOT EXISTS

select date, id from table1 t1
where not exists (select 1 from table2 t2
                  where t1.date = t2.date
                    and t1.id = t2.id)

已修改:已将and t1.id = t2.id添加到NOT EXISTS版本的子选择中。

答案 1 :(得分:2)

简单

select date, id from table1 
where not exists(select 'x' from table2 where table1.date = table2.date)

答案 2 :(得分:1)

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE T1 ( "DATE", ID ) AS
SELECT DATE '2015-01-01' + LEVEL - 1, 10
FROM   DUAL
CONNECT BY LEVEL < 7;

CREATE TABLE T2 ( "DATE", ID ) AS
SELECT DATE '2015-01-03', 10 FROM DUAL;

查询1

SELECT * FROM T1
MINUS
SELECT * FROM T2

<强> Results

|                      DATE | ID |
|---------------------------|----|
| January, 01 2015 00:00:00 | 10 |
| January, 02 2015 00:00:00 | 10 |
| January, 04 2015 00:00:00 | 10 |
| January, 05 2015 00:00:00 | 10 |
| January, 06 2015 00:00:00 | 10 |

查询2

SELECT * FROM T1
WHERE NOT EXISTS ( SELECT 'X'
                   FROM   T2
                   WHERE  T1.ID = T2.ID
                   AND    T1."DATE" = T2."DATE" )

<强> Results

|                      DATE | ID |
|---------------------------|----|
| January, 01 2015 00:00:00 | 10 |
| January, 05 2015 00:00:00 | 10 |
| January, 04 2015 00:00:00 | 10 |
| January, 06 2015 00:00:00 | 10 |
| January, 02 2015 00:00:00 | 10 |

查询3

此查询在SQL Server中有效,但在Oracle中无效:

SELECT * FROM T1
EXCEPT ALL
SELECT * FROM T2

<强> Results

ORA-00933: SQL command not properly ended 

答案 3 :(得分:0)

另一种方式,

SQL> SELECT t1.* FROM t1, t2 WHERE t1."DATE" <> t2."DATE" AND t1.ID = t2.ID;

DATE              ID
--------- ----------
01-JAN-15         10
02-JAN-15         10
04-JAN-15         10
05-JAN-15         10
06-JAN-15         10

不同的ID可能有不同的假期,因此条件会检查不匹配的行并将其过滤掉并确保检查特定的ID而不是随机的。

性能的角度来看,通过适当的主键和外键约束,您可以在引用表上执行单个表扫描,而不是2个表扫描。

例如,

添加主键外键约束:

SQL> ALTER TABLE t1
  2  ADD CONSTRAINT t1_pk PRIMARY KEY ("DATE", id);

Table altered.

SQL>
SQL> ALTER TABLE t2
  2  ADD CONSTRAINT t2_fk
  3     FOREIGN KEY ("DATE", ID)
  4     REFERENCES t1 ("DATE", id);

Table altered.

让我们检查解释计划

SQL> set autot on explain
SQL> SELECT t1.* FROM t1, t2 WHERE t1."DATE" <> t2."DATE" AND t1.ID = t2.ID;

DATE              ID
--------- ----------
01-JAN-15         10
02-JAN-15         10
04-JAN-15         10
05-JAN-15         10
06-JAN-15         10


Execution Plan
----------------------------------------------------------
Plan hash value: 603358195

----------------------------------------------------------------------------
| Id  | Operation          | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |       |     5 |   110 |     4   (0)| 00:00:01 |
|   1 |  NESTED LOOPS      |       |     5 |   110 |     4   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| T2    |     1 |    11 |     3   (0)| 00:00:01 |
|*  3 |   INDEX FULL SCAN  | T1_PK |     5 |    55 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("T1"."ID"="T2"."ID")
       filter("T1"."DATE"<>"T2"."DATE" AND "T1"."ID"="T2"."ID")

Note
-----
   - this is an adaptive plan

因此,只有T2上的全表扫描T1的主键索引上的 INDEX FULL SCAN 。< / p>

现在,外键应该有一个支持索引,这将避免全表扫描并使用索引扫描

让我们为外键创建支持指数

SQL> CREATE INDEX t2_indx ON t2("DATE", id);

Index created.

让我们检查解释计划

SQL> set autot on explain
SQL> SELECT t1.* FROM t1, t2 WHERE t1."DATE" <> t2."DATE" AND t1.ID = t2.ID;

DATE              ID
--------- ----------
01-JAN-15         10
02-JAN-15         10
04-JAN-15         10
05-JAN-15         10
06-JAN-15         10


Execution Plan
----------------------------------------------------------
Plan hash value: 2278991468

----------------------------------------------------------------------------
| Id  | Operation        | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT |         |     5 |   110 |     2   (0)| 00:00:01 |
|   1 |  NESTED LOOPS    |         |     5 |   110 |     2   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN| T2_INDX |     1 |    11 |     1   (0)| 00:00:01 |
|*  3 |   INDEX FULL SCAN| T1_PK   |     5 |    55 |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("T1"."ID"="T2"."ID")
       filter("T1"."DATE"<>"T2"."DATE" AND "T1"."ID"="T2"."ID")

Note
-----
   - this is an adaptive plan

现在,没有全表扫描,而优化程序使用 INDEX FULL SCAN