oracle里面Union和minus的问题

oracle里面Union和minus的问题,第1张

补充:你仔细看看我的回答

你下面的想法是错误的

select from A minus select from B ={1,2,3,6,7,8}

SQL> select from test001;

NAME

----------

1

2

3

4

5

SQL> select from test002;

NAME

----------

4

5

6

7

8

SQL> select from test001 minus select from test002;

NAME

----------

1

2

3

SQL> select from test001 union select from test002;

NAME

----------

1

2

3

4

5

6

7

8

按照上面的结果,查询ab交集只需要

select from A minus (select from A minus select from B);

SQL> select from test001 minus (select from test001 minus select from test002);

NAME

----------

4

5

MINUS 指令是运用在两个 SQL 语句上。它先找出第一个 SQL 语句所产生的结果,然后看这些结果有没有在第二个 SQL 语句的结果中。如果有的话,那这一笔资料就被去除,而不会在最后的结果中出现。如果第二个 SQL 语句所产生的结果并没有存在于第一个 SQL 语句所产生的结果内,那这笔资料就被抛弃。

我们继续使用一样的例子:

Store_Information 表格

store_name Sales Date

Los Angeles $1500 Jan-05-1999

San Diego $250 Jan-07-1999

Los Angeles $300 Jan-08-1999

Boston $700 Jan-08-1999

Internet Sales 表格 Date Sales

Jan-07-1999 $250

Jan-10-1999 $535

Jan-11-1999 $320

Jan-12-1999 $750

而我们要知道有哪几天是有店面营业额而没有网络营业额的。要达到这个目的,我们用以下的 SQL 语句:

SELECT Date FROM Store_Information

MINUS

SELECT Date FROM Internet_Sales

结果:

Date

Jan-05-1999

Jan-08-1999

简单列子

select '115' from dual

minus

select '150' from dual

结果是

115

UNION 指令的目的是将两个 SQL 语句的结果合并起来。从这个角度来看, UNION 跟 JOIN 有些许类似,因为这两个指令都可以由多个表格中撷取资料。 UNION 的一个限制是两个 SQL 语句所产生的栏位需要是同样的资料种类。另外,当我们用 UNION这个指令时,我们只会看到不同的资料值 (类似 SELECT DISTINCT)。

假设我们有以下的两个表格,

表格: Store_Information

store_name Sales Date

Los Angeles $1500 Jan-05-1999

San Diego $250 Jan-07-1999

Los Angeles $300 Jan-08-1999

Boston $700 Jan-08-1999

表格: Internet Sales

Date Sales

Jan-07-1999 $250

Jan-10-1999 $535

Jan-11-1999 $320

Jan-12-1999 $750

而我们要找出来所有有营业额 (sales) 的日子。要达到这个目的,我们用以下的 SQL 语句:

SELECT Date FROM Store_Information

UNION

SELECT Date FROM Internet_Sales

结果:

Date

Jan-05-1999

Jan-07-1999

Jan-08-1999

Jan-10-1999

Jan-11-1999

Jan-12-1999

简单列子

select '115' from dual

union

select '150' from dual

结果是:

115

150

补充一下,

oracle中不能使用not minus

对于rownum来说它是oracle系统顺序分配为从查询返回的行的编号 返回的第一行分配的是 第二行是 依此类推 这个伪字段可以用于限制查询返回的总行数 而且rownum不能以任何表的名称作为前缀

举例说明

例如表 student(学生)表 表结构为

ID           varchar ( ) 学号

namevarchar ( )  姓名

create table student (ID varchar ( ) name varchar ( ));

insert into student values( 张一 );

insert into student values( 王二 );

insert into student values( 李三 );

insert into student values( 赵四 );

mit;

( ) rownum 对于等于某值的查询条件

如 果希望找到学生表中第一条学生的信息 可以使用rownum= 作为条件 但是想找到学生表中第二条学生的信息 使用rownum= 结果查不到数据 因 为rownum都是从 开始 但是 以上的自然数在rownum做等于判断是时认为都是false条件 所以无法查到rownum = n(n> 的自然数)

SQL> select rownum id name from student where rownum= ;(可以用在限制返回记录条数的地方 保证不出错 如 隐式游标)

SQL> select rownum id name from student where rownum= ;

ROWNUM ID     NAME

张一

SQL> select rownum id name from student where rownum = ;

ROWNUM ID     NAME

( )rownum对于大于某值的查询条件

如果想找到从第二行记录以后的记录 当使用rownum> 是查不出记录的 原因是由于rownum是一个总是从 开始的伪列 Oracle 认为rownum> n(n> 的自然数)这种条件依旧不成立 所以查不到记录

SQL> select rownum id name from student where rownum > ;

ROWNUM ID     NAME

那如何才能找到第二行以后的记录呀 可以使用以下的子查询方法来解决 注意子查询中的rownum必须要有别名 否则还是不会查出记录来 这是因为rownum不是某个表的列 如果不起别名的话 无法知道rownum是子查询的列还是主查询的列

SQL>select from(select rownum no id name from student) where no> ;

NO ID     NAME

李三

赵四

SQL> select from(select rownum id name from student)where rownum> ;

ROWNUM ID     NAME

( )rownum对于小于某值的查询条件

如果想找到第三条记录以前的记录 当使用rownum< 是能得到两条记录的 显然rownum对于rownum<n((n> 的自然数)的条件认为是成立的 所以可以找到记录

SQL> select rownum id name from student where rownum < ;

ROWNUM ID     NAME

张一

王二

综 上几种情况 可能有时候需要查询rownum在某区间的数据 那怎么办呀从上可以看出rownum对小于某值的查询条件是人为true的 rownum对 于大于某值的查询条件直接认为是false的 但是可以间接的让它转为认为是true的 那就必须使用子查询 例如要查询rownum在第二行到第三行之 间的数据 包括第二行和第三行数据 那么我们只能写以下语句 先让它返回小于等于三的记录行 然后在主查询中判断新的rownum的别名列大于等于二的记 录行 但是这样的 *** 作会在大数据集中影响速度

SQL> select from (select rownum no id name from student where rownum<= ) where no >= ;

NO ID     NAME

王二

李三

( )rownum和排序

Oracle中的rownum的是在取数据的时候产生的序号 所以想对指定排序的数据去指定的rowmun行数据就必须注意了

SQL> select rownum id name from student order by name;

ROWNUM ID     NAME

李三

王二

张一

赵四

可以看出 rownum并不是按照name列来生成的序号 系统是按照记录插入时的顺序给记录排的号 rowid也是顺序分配的 为了解决这个问题 必须使用子查询

SQL> select rownum id name from (select from student order by name);

ROWNUM ID     NAME

李三

王二

张一

赵四

这样就成了按name排序 并且用rownum标出正确序号(有小到大)

笔者在工作中有一上百万条记录的表 在jsp页面中需对该表进行分页显示 便考虑用rownum来作 下面是具体方法(每页

显示 条)

select from tabname where rownum< order by name 但却发现oracle却不能按自己的意愿来执行 而是先随便取 条记录 然后再 order by 后经咨询oracle 说rownum确实就这样 想用的话 只能用子查询 来实现先排序 后rownum 方法如下

select from (select from tabname order by name) where rownum< 但这样一来 效率会较低很多

后经笔者试验 只需在order by 的字段上加主键或索引即可让oracle先按 该字段排序 然后再rownum 方法不变

select from tabname where rownum< order by name

取得某列中第N大的行

select column_name from

(select table_name dense_rank() over (order by column desc) rank from table_name)

where rank = &N

假如要返回前 条记录

select from tablename where rownum< ;(或是rownum <= 或是rownum != )

假如要返回第 条记录

select from tablename

where …

and rownum<

minus

select from tablename

where …

and rownum<

order by name

选出结果后用name排序显示结果 (先选再排序)

注意 只能用以上符号(< <= !=)

select from tablename where rownum != ;返回的是前9条记录

不能用 > >= = Beeen and 由于rownum是一个总是从 开始的伪列 Oracle 认为这种条件 不成立 查不到记录

另外 这个方法更快

select from (

select rownum r a from yourtable

where rownum <=

order by name )

where r >

这样取出第 条记录!(先选再排序再选)

要先排序再选则须用select嵌套 内层排序外层选 rownum是随着结果集生成的 一旦生成 就不会变化了 同时 生成的结果是依次递加的 没有 就永远不会有 rownum 是在 查询集合产生的过程中产生的伪列 并且如果where条件中存在 rownum 条件的话 则:

假如 判定条件是常量 则

只能 rownum = <= 大于 的自然数 = 大于 的数是没有结果的 大于一个数也是没有结果的

即 当出现一个 rownum 不满足条件的时候则 查询结束 this is stop key!

: 当判定值不是常量的时候

lishixinzhi/Article/program/Oracle/201311/17923

EXCEPT和MINUS *** 作符

数据库程序设计的目标就是最大限度地减少需要通过网络传送的数据量 并消除客户端不必要的处理过程 也就是说 只向RDBMS请求需要的数据 不触动其余任何之物 INTERSECT *** 作符可以求取两个查询结果的交集 而EXCEPT *** 作符则用于求取两个查询结果的差集

INTERSECT *** 作符和EXCEPT *** 作符是一种便利的表示方式 可以使用INNER JOIN和OUTER JOIN来分别替代它们(加上某些调整 消除重复的记录)

在上面的例子中 如果使用EXCEPT *** 作符代替INTERSECT *** 作符 查询结果将显示在书柜上还没有分配到位置的所有图书(即在LOCATION表中没有相应的记录)

SELECT bk_id FROM books

EXCEPT

SELECT fk_bk_loc FROM location;

bk_id

( row(s) affected)

该查询仅返回在BOOKS表中存在的同时在LOCATION表中不存在相应记录的记录 在本章结尾的练习中将尝试使用INTERSECT *** 作符和EXCEPT *** 作符

可以使用NOT EXISTS *** 作符和相关子查询来代替EXCEPT(或MINUS)关键字 虽然没有获得SQL标准委员会的官方支持 但所有RDBMS都支持这种语法(除了在OpenOffice中作为嵌入式RDBMS的HSQLDB例外)

DB Microsoft SQL Server和PostgreSQL都实现了EXCEPT关键字 Oracle则使用MINUS关键字 MySQL和HSQLDB既支持EXCEPT *** 作符 又支持MINUS关键字 Microsoft Access对两者都不支持

试一试求取数据集的差集

为了进一步观察数据集 *** 作符(例如INTERSECT *** 作符和EXCEPT *** 作符)的使用 下面将在已经完美匹配的数据中添加一些新数据 在本章之前讨论LEFT OUTER JOIN时已经执行过类似的 *** 作 在下面的练习中可以再次使用相同的记录

接下来将在BOOKS表中添加一条不匹配的记录 用于演示INTERSECT *** 作符和EXCEPT *** 作符的应用

( ) 打开Microsoft SQL Server Management Studio 使用Windows身份验证连接到数据库

( ) 单击位于左上角的New Query按钮

( ) 在打开的查询窗口(中间的窗格)中输入下面的SQL查询

INSERT INTO books (bk_id bk_title)

VALUES ( UNMATCHED RECORD )

( ) 现在BOOKS表中已经具有一条新记录 该记录在LOCATION表中没有对应的位置 此时使用INTERSECT *** 作符和EXCEPT *** 作符将查询到什么结果呢?首先 执行一个使用INTERSECT *** 作符的查询

SELECT bk_id FROM books

INTERSECT

SELECT fk_bk_loc FROM location;

( ) 可以预见 该查询只会返回 条记录 BOOKS表与LOCATION表中都匹配的记录

( ) 运行使用EXCEPT *** 作符的查询将产生一个不同的结果

SELECT bk_id FROM books

EXCEPT

SELECT fk_bk_loc FROM location;

bk_id

( row(s) affected)

示例说明

在将一条新记录插入到BOOKS表之后 BOOKS表中包含了 条记录 但只有 条记录在LOCATION表中具有相匹配的记录 这模拟了买到一本新书但还没有在书柜中分配图书摆放位置的情形 INTERSECT *** 作符仅返回那些在两个表中都匹配的记录 因此 BK_ID = 的记录将被排除在外

当运行EXCEPT查询时 将分别从BOOKS表和LOCATION表中抽取匹配的记录 并将不匹配的记录返回 在本例中 不匹配的记录就是新插入的UNMATCHED RECORD这条记录

       返回目录 SQL实战新手入门

       编辑推荐

       Oracle索引技术

       高性能MySQL

lishixinzhi/Article/program/SQL/201311/16454

以上就是关于oracle里面Union和minus的问题全部的内容,包括:oracle里面Union和minus的问题、oracle中的可不可以not minus的用法、Oracle应用——rownum等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9828719.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-02
下一篇 2023-05-02

发表评论

登录后才能评论

评论列表(0条)

保存