sql脚本---not exists(转帖)

SQL code ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
--按某一字段分组取最大(小)值所在行的数据
--(爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开) 2007-10-23于浙江杭州)
/*
数据如下:
name  val memo
a    2   a2(a的第二个值)
a    1   a1 --a的第一个值
a    3   a3:a的第三个值
b    1   b1 --b的第一个值
b    3   b3:b的第三个值
b    2   b2b2b2b2
b    4   b4b4
b    5   b5b5b5b5b5
*/
--创建表并插入数据:
create  table  tb( name  varchar (10),val  int ,memo  varchar (20))
insert  into  tb  values ( 'a' ,    2,    'a2(a的第二个值)' )
insert  into  tb  values ( 'a' ,    1,    'a1--a的第一个值' )
insert  into  tb  values ( 'a' ,    3,    'a3:a的第三个值' )
insert  into  tb  values ( 'b' ,    1,    'b1--b的第一个值' )
insert  into  tb  values ( 'b' ,    3,    'b3:b的第三个值' )
insert  into  tb  values ( 'b' ,    2,    'b2b2b2b2' )
insert  into  tb  values ( 'b' ,    4,    'b4b4' )
insert  into  tb  values ( 'b' ,    5,    'b5b5b5b5b5' )
go
 
--一、按name分组取val最大的值所在行的数据。
--方法1:
select  a.*  from  tb a  where  val = ( select  max (val)  from  tb  where  name  = a. name order  by  a. name
--方法2:
select  a.*  from  tb a  where  not  exists( select  from  tb  where  name  = a. name  and  val > a.val)
--方法3:
select  a.*  from  tb a,( select  name , max (val) val  from  tb  group  by  name ) b  where  a. name  = b. name  and  a.val = b.val  order  by  a. name
--方法4:
select  a.*  from  tb a  inner  join  ( select  name  max (val) val  from  tb  group  by  name ) b  on  a. name  = b. name  and  a.val = b.val  order  by  a. name
--方法5
select  a.*  from  tb a  where  1 > ( select  count (*)  from  tb  where  name  = a. name  and  val > a.val )  order  by  a. name
/*
name        val         memo                 
---------- ----------- -------------------- 
a          3           a3:a的第三个值
b          5           b5b5b5b5b5
*/
 
--二、按name分组取val最小的值所在行的数据。
--方法1:
select  a.*  from  tb a  where  val = ( select  min (val)  from  tb  where  name  = a. name order  by  a. name
--方法2:
select  a.*  from  tb a  where  not  exists( select  from  tb  where  name  = a. name  and  val < a.val)
--方法3:
select  a.*  from  tb a,( select  name , min (val) val  from  tb  group  by  name ) b  where  a. name  = b. name  and  a.val = b.val  order  by  a. name
--方法4:
select  a.*  from  tb a  inner  join  ( select  name  min (val) val  from  tb  group  by  name ) b  on  a. name  = b. name  and  a.val = b.val  order  by  a. name
--方法5
select  a.*  from  tb a  where  1 > ( select  count (*)  from  tb  where  name  = a. name  and  val < a.val)  order  by  a. name
/*
name        val         memo                 
---------- ----------- -------------------- 
a          1           a1 --a的第一个值
b          1           b1 --b的第一个值
*/
 
--三、按name分组取第一次出现的行所在的数据。
select  a.*  from  tb a  where  val = ( select  top  1 val  from  tb  where  name  = a. name order  by  a. name
/*
name        val         memo                 
---------- ----------- -------------------- 
a          2           a2(a的第二个值)
b          1           b1 --b的第一个值
*/
 
--四、按name分组随机取一条数据。
select  a.*  from  tb a  where  val = ( select  top  1 val  from  tb  where  name  = a. name  order  by  newid())  order  by  a. name
/*
name        val         memo                 
---------- ----------- -------------------- 
a          1           a1 --a的第一个值
b          5           b5b5b5b5b5
*/
 
--五、按name分组取最小的两个(N个)val
select  a.*  from  tb a  where  2 > ( select  count (*)  from  tb  where  name  = a. name  and  val < a.val )  order  by  a. name ,a.val
select  a.*  from  tb a  where  val  in  ( select  top  2 val  from  tb  where  name =a. name  order  by  val)  order  by  a. name ,a.val
select  a.*  from  tb a  where  exists ( select  count (*)  from  tb  where  name  = a. name  and  val < a.val  having  Count (*) < 2)  order  by  a. name ,a.val
/*
name        val         memo                 
---------- ----------- -------------------- 
a          1           a1 --a的第一个值
a          2           a2(a的第二个值)
b          1           b1 --b的第一个值
b          2           b2b2b2b2
*/
 
--六、按name分组取最大的两个(N个)val
select  a.*  from  tb a  where  2 > ( select  count (*)  from  tb  where  name  = a. name  and  val > a.val )  order  by  a. name ,a.val
select  a.*  from  tb a  where  val  in  ( select  top  2 val  from  tb  where  name =a. name  order  by  val  desc order  by  a. name ,a.val
select  a.*  from  tb a  where  exists ( select  count (*)  from  tb  where  name  = a. name  and  val > a.val  having  Count (*) < 2)  order  by  a. name  , a.val
/*
name        val         memo                 
---------- ----------- -------------------- 
a          2           a2(a的第二个值)
a          3           a3:a的第三个值
b          4           b4b4
b          5           b5b5b5b5b5
*/
--七,如果整行数据有重复,所有的列都相同。
/*
数据如下:
name  val memo
a    2   a2(a的第二个值)
a    1   a1 --a的第一个值
a    1   a1 --a的第一个值
a    3   a3:a的第三个值
a    3   a3:a的第三个值
b    1   b1 --b的第一个值
b    3   b3:b的第三个值
b    2   b2b2b2b2
b    4   b4b4
b    5   b5b5b5b5b5
*/
--在sql server 2000中只能用一个临时表来解决,生成一个自增列,先对val取最大或最小,然后再通过自增列来取数据。
--创建表并插入数据:
create  table  tb( name  varchar (10),val  int ,memo  varchar (20))
insert  into  tb  values ( 'a' ,    2,    'a2(a的第二个值)' )
insert  into  tb  values ( 'a' ,    1,    'a1--a的第一个值' )
insert  into  tb  values ( 'a' ,    1,    'a1--a的第一个值' )
insert  into  tb  values ( 'a' ,    3,    'a3:a的第三个值' )
insert  into  tb  values ( 'a' ,    3,    'a3:a的第三个值' )
insert  into  tb  values ( 'b' ,    1,    'b1--b的第一个值' )
insert  into  tb  values ( 'b' ,    3,    'b3:b的第三个值' )
insert  into  tb  values ( 'b' ,    2,    'b2b2b2b2' )
insert  into  tb  values ( 'b' ,    4,    'b4b4' )
insert  into  tb  values ( 'b' ,    5,    'b5b5b5b5b5' )
go
 
select  * , px = identity( int ,1,1)  into  tmp  from  tb
 
select  m. name ,m.val,m.memo  from
(
   select  t.*  from  tmp t  where  val = ( select  min (val)  from  tmp  where  name  = t. name )
) m  where  px = ( select  min (px)  from
(
   select  t.*  from  tmp t  where  val = ( select  min (val)  from  tmp  where  name  = t. name )
) n  where  n. name  = m. name )
 
drop  table  tb,tmp
 
/*
name        val         memo
---------- ----------- --------------------
a          1           a1 --a的第一个值
b          1           b1 --b的第一个值
 
(2 行受影响)
*/
--在sql server 2005中可以使用row_number函数,不需要使用临时表。
--创建表并插入数据:
create  table  tb( name  varchar (10),val  int ,memo  varchar (20))
insert  into  tb  values ( 'a' ,    2,    'a2(a的第二个值)' )
insert  into  tb  values ( 'a' ,    1,    'a1--a的第一个值' )
insert  into  tb  values ( 'a' ,    1,    'a1--a的第一个值' )
insert  into  tb  values ( 'a' ,    3,    'a3:a的第三个值' )
insert  into  tb  values ( 'a' ,    3,    'a3:a的第三个值' )
insert  into  tb  values ( 'b' ,    1,    'b1--b的第一个值' )
insert  into  tb  values ( 'b' ,    3,    'b3:b的第三个值' )
insert  into  tb  values ( 'b' ,    2,    'b2b2b2b2' )
insert  into  tb  values ( 'b' ,    4,    'b4b4' )
insert  into  tb  values ( 'b' ,    5,    'b5b5b5b5b5' )
go
 
select  m. name ,m.val,m.memo  from
(
   select  * , px = row_number() over( order  by  name  , val)  from  tb
) m  where  px = ( select  min (px)  from
(
   select  * , px = row_number() over( order  by  name  , val)  from  tb
) n  where  n. name  = m. name )
 
drop  table  tb
 
/*
name        val         memo
---------- ----------- --------------------
a          1           a1 --a的第一个值
b          1           b1 --b的第一个值
 
(2 行受影响)
*/

EXISTS 用法。

SQL code ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
exists (sql 返回结果集为真) 
not  exists (sql 不返回结果集为真) 
如下: 
表A 
ID  NAME 
1    A1 
2    A2 
3  A3 
 
表B 
ID AID  NAME 
1    1 B1 
2    2 B2 
3    2 B3 
 
表A和表B是1对多的关系 A.ID => B.AID 
 
SELECT  ID, NAME  FROM  WHERE  EXIST ( SELECT  FROM  WHERE  A.ID=B.AID) 
执行结果为 
1 A1 
2 A2 
原因可以按照如下分析 
SELECT  ID, NAME  FROM  WHERE  EXISTS ( SELECT  FROM  WHERE  B.AID=1) 
--->SELECT * FROM B WHERE B.AID=1有值返回真所以有数据 
 
SELECT  ID, NAME  FROM  WHERE  EXISTS ( SELECT  FROM  WHERE  B.AID=2) 
--->SELECT * FROM B WHERE B.AID=2有值返回真所以有数据 
 
SELECT  ID, NAME  FROM  WHERE  EXISTS ( SELECT  FROM  WHERE  B.AID=3) 
--->SELECT * FROM B WHERE B.AID=3无值返回真所以没有数据 
 
NOT  EXISTS 就是反过来 
SELECT  ID, NAME  FROM  WHERE   NOT  EXIST ( SELECT  FROM  WHERE  A.ID=B.AID) 
执行结果为 
3 A3 
=========================================================================== 
EXISTS =  IN ,意思相同不过语法上有点点区别,好像使用 IN 效率要差点,应该是不会执行索引的原因 
SELECT  ID, NAME  FROM  A   WHERE  ID  IN  ( SELECT  AID  FROM  B) 
 
NOT  EXISTS =  NOT  IN  ,意思相同不过语法上有点点区别 
SELECT  ID, NAME  FROM  WHERE  ID  NOT  IN  ( SELECT  AID  FROM  B) 
 
 
下面是普通的用法: 
 
SQL中 IN , NOT  IN ,EXISTS, NOT  EXISTS的用法和差别: 
   IN :确定给定的值是否与子查询或列表中的值相匹配。 
   IN  关键字使您得以选择与列表中的任意一个值匹配的行。 
  当要获得居住在 California、Indiana 或 Maryland 州的所有作者的姓名和州的列表时,就需要下列查询: 
   SELECT  ProductID, ProductName  FROM  Northwind.dbo.Products  WHERE  CategoryID = 1  OR  CategoryID = 4  OR  CategoryID = 5 
  然而,如果使用  IN ,少键入一些字符也可以得到同样的结果: 
   SELECT  ProductID, ProductName  FROM  Northwind.dbo.Products  WHERE  CategoryID  IN  (1, 4, 5) 
   IN  关键字之后的项目必须用逗号隔开,并且括在括号中。 
  下列查询在 titleauthor 表中查找在任一种书中得到的版税少于 50% 的所有作者的 au_id,然后从 authors 表中选择 au_id 与 
  titleauthor 查询结果匹配的所有作者的姓名: 
   SELECT  au_lname, au_fname  FROM  authors  WHERE  au_id  IN  ( SELECT  au_id  FROM  titleauthor  WHERE  royaltyper <50) 
  结果显示有一些作者属于少于 50% 的一类。 
   NOT  IN :通过  NOT  IN  关键字引入的子查询也返回一列零值或更多值。 
  以下查询查找没有出版过商业书籍的出版商的名称。 
   SELECT  pub_name  FROM  publishers  WHERE  pub_id  NOT  IN  ( SELECT  pub_id  FROM  titles  WHERE  type =  'business'
  使用 EXISTS 和  NOT  EXISTS 引入的子查询可用于两种集合原理的操作:交集与差集。 
       两个集合的交集包含同时属于两个原集合的所有元素。 
  差集包含只属于两个集合中的第一个集合的元素。 
  EXISTS:指定一个子查询,检测行的存在。 
  本示例所示查询查找由位于以字母 B 开头的城市中的任一出版商出版的书名: 
   SELECT  DISTINCT  pub_name  FROM  publishers  WHERE  EXISTS ( SELECT  FROM  titles  WHERE  pub_id = publishers.pub_id  AND  type = 
   'business'
   SELECT  distinct  pub_name  FROM  publishers  WHERE  pub_id  IN  ( SELECT  pub_id  FROM  titles  WHERE  type =  'business'
  两者的区别: 
  EXISTS:后面可以是整句的查询语句如: SELECT  FROM  titles 
   IN :后面只能是对单列: SELECT  pub_id  FROM  titles 
   NOT  EXISTS: 
  例如,要查找不出版商业书籍的出版商的名称: 
   SELECT  pub_name  FROM  publishers  WHERE  NOT  EXISTS ( SELECT  FROM  titles  WHERE  pub_id = publishers.pub_id  AND  type = 
   'business'
  下面的查询查找已经不销售的书的名称: 
   SELECT  title  FROM  titles  WHERE  NOT  EXISTS ( SELECT  title_id  FROM  sales  WHERE  title_id = titles.title_id) 
 
语法 
 
EXISTS subquery 
参数 
subquery:是一个受限的  SELECT  语句 (不允许有 COMPUTE 子句和  INTO  关键字)。有关更多信息,请参见  SELECT  中有关子查询的讨论。 
 
结果类型:Boolean 
 
 
结果值:如果子查询包含行,则返回  TRUE 。 
 
 
示例 
A. 在子查询中使用  NULL  仍然返回结果集 
 
这个例子在子查询中指定  NULL ,并返回结果集,通过使用 EXISTS 仍取值为  TRUE 。 
 
USE Northwind 
GO 
SELECT  CategoryName 
FROM  Categories 
WHERE  EXISTS ( SELECT  NULL
ORDER  BY  CategoryName  ASC 
GO 
 
B. 比较使用 EXISTS 和  IN  的查询 
 
这个例子比较了两个语义类似的查询。第一个查询使用 EXISTS 而第二个查询使用  IN 。注意两个查询返回相同的信息。 
 
USE pubs 
GO 
SELECT  DISTINCT  pub_name 
FROM  publishers 
WHERE  EXISTS 
     ( SELECT 
     FROM  titles 
     WHERE  pub_id = publishers.pub_id 
     AND  type = \'business\') 
GO 
 
-- Or, using the IN clause: 
 
USE pubs 
GO 
SELECT  distinct  pub_name 
FROM  publishers 
WHERE  pub_id  IN 
     ( SELECT  pub_id 
     FROM  titles 
     WHERE  type = \'business\') 
GO 
 
 
下面是任一查询的结果集: 
 
pub_name                                
---------------------------------------- 
Algodata Infosystems                    
New Moon Books                          
 
C.比较使用 EXISTS 和 =  ANY  的查询 
 
本示例显示查找与出版商住在同一城市中的作者的两种查询方法:第一种方法使用 =  ANY ,第二种方法使用 EXISTS。注意这两种方法返回相同的信息。 
 
USE pubs 
GO 
SELECT  au_lname, au_fname 
FROM  authors 
WHERE  exists 
     ( SELECT 
     FROM  publishers 
     WHERE  authors.city = publishers.city) 
GO 
 
-- Or, using = ANY 
 
USE pubs 
GO 
SELECT  au_lname, au_fname 
FROM  authors 
WHERE  city =  ANY 
     ( SELECT  city 
     FROM  publishers) 
GO 
 
 
D.比较使用 EXISTS 和  IN  的查询 
 
本示例所示查询查找由位于以字母 B 开头的城市中的任一出版商出版的书名: 
 
USE pubs 
GO 
SELECT  title 
FROM  titles 
WHERE  EXISTS 
     ( SELECT 
     FROM  publishers 
     WHERE  pub_id = titles.pub_id 
     AND  city  LIKE  \'B%\') 
GO 
 
-- Or, using IN: 
 
USE pubs 
GO 
SELECT  title 
FROM  titles 
WHERE  pub_id  IN 
     ( SELECT  pub_id 
     FROM  publishers 
     WHERE  city  LIKE  \'B%\') 
GO 
 
 
E. 使用  NOT  EXISTS 
 
NOT  EXISTS 的作用与 EXISTS 正相反。如果子查询没有返回行,则满足  NOT  EXISTS 中的  WHERE  子句。本示例查找不出版商业书籍的出版商的名称: 
 
USE pubs 
GO 
SELECT  pub_name 
FROM  publishers 
WHERE  NOT  EXISTS 
     ( SELECT 
     FROM  titles 
     WHERE  pub_id = publishers.pub_id 
     AND  type = \'business\') 
ORDER  BY  pub_name 
GO 

猜你喜欢

转载自breakingbad.iteye.com/blog/2196046
今日推荐