现在的位置: 首页 > 综合 > 正文

SQL里的EXISTS与in、not exists与not in 效率比较和使用

2018年05月04日 ⁄ 综合 ⁄ 共 4398字 ⁄ 字号 评论关闭

 http://www.cnblogs.com/thunderdanky/articles/818864.html

在 MSSQL 中,插入(insert)一条记录很简单,但是一些特殊应用,在插入记录前,需要检查这条记录是否已经存在,只有当记录不存在时才执行插入操作,本文介绍的就是这个问题的解决方案。

问题:我创建了一个表来存放客户信息,我知道可以用 insert 语句插入信息到表中,但是怎么样才能保证不会插入重复的记录呢?

答案:可以通过使用 EXISTS 条件句防止插入重复记录。

示例一:插入多条记录

假设有一个主键为 client_id 的 clients 表,可以使用下面的语句:

Code:

INSERT INTO clients
(client_id, client_name, client_type)
SELECT supplier_id, supplier_name, 'advertising'
FROM suppliers
WHERE not exists (select * from clients
where clients.client_id = suppliers.supplier_id);

示例一:插入单条记录

Code:

INSERT INTO clients
(client_id, client_name, client_type)
SELECT 10345, 'IBM', 'advertising'
FROM dual
WHERE not exists (select * from clients
where clients.client_id = 10345);

使用 dual 做表名可以让你在 select 语句后面直接跟上要插入字段的值,即使这些值还不存在当前表中。

系统要求进行SQL优化,对效率比较低的SQL进行优化,使其运行效率更高,其中要求对SQL中的部分in/not in修改为exists/not exists

 

修改方法如下:

in的SQL语句

SELECT id, category_id, htmlfile, title, convert(varchar(20),begintime,112) as pubtime
FROM tab_oa_pub WHERE is_check=1 and
category_id in (select id from tab_oa_pub_cate where no='1')
order by begintime desc

修改为exists的SQL语句
SELECT id, category_id, htmlfile, title, convert(varchar(20),begintime,112) as pubtime
FROM tab_oa_pub WHERE is_check=1 and
exists (select id from tab_oa_pub_cate where tab_oa_pub.category_id=convert(int,no) and no='1')
order by begintime desc

 

分析一下exists真的就比in的效率高吗?

 

    我们先讨论IN和EXISTS。
    select * from t1 where x in ( select y from t2 )
    事实上可以理解为:
    select *
      from t1, ( select distinct y from t2 ) t2
     where t1.x = t2.y;
    ——如果你有一定的SQL优化经验,从这句很自然的可以想到t2绝对不能是个大表,因为需要对t2进行全表的“唯一排序”,如果t2很大这个排序的性能是不可忍受的。但是t1可以很大,为什么呢?最通俗的理解就是因为t1.x=t2.y可以走索引。但这并不是一个很好的解释。试想,如果t1.x和t2.y都有索引,我们知道索引是种有序的结构,因此t1和t2之间最佳的方案是走merge join。另外,如果t2.y上有索引,对t2的排序性能也有很大提高。
    select * from t1 where exists ( select null from t2 where y = x )
    可以理解为:
    for x in ( select * from t1 )
    loop
       if ( exists ( select null from t2 where y = x.x )
       then
          OUTPUT THE RECORD!
       end if
    end loop
    ——这个更容易理解,t1永远是个表扫描!因此t1绝对不能是个大表,而t2可以很大,因为y=x.x可以走t2.y的索引。
    综合以上对IN/EXISTS的讨论,我们可以得出一个基本通用的结论:IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况。

我们要根据实际的情况做相应的优化,不能绝对的说谁的效率高谁的效率低,所有的事都是相对的

 

0
0

(请您对文章做出评价)
posted on 2007-07-15 18:06 Thunderdanky 阅读(3034) 评论(3)  编辑 收藏 网摘 所属分类: .NET技术文章


FeedBack:

2007-11-07 09:36 | ne[未注册用户]
使用INNER JOIN 替代 EXIST 来提高查询效率
Rewrite Subqueries to Use JOIN
Sometimes you can rewrite a subquery to use JOIN and achieve better performance. The advantage of creating a JOIN is that you can evaluate tables in a different order from that defined by the query. The advantage of using a subquery is that it is frequently not necessary to scan all rows from the subquery to evaluate the subquery expression. For example, an EXISTS subquery can return TRUE upon seeing the first qualifying row.

Note:
The SQL Server Compact 3.5 query processor always rewrites the IN subquery to use JOIN. You do not have to try this approach with queries that contain the IN subquery clause.

For example, to determine all the orders that have at least one item with a 25 percent discount or more, you can use the following EXISTS subquery:

SELECT "Order ID" FROM Orders O

WHERE EXISTS (SELECT "Order ID"

FROM "Order Details" OD

WHERE O."Order ID" = OD."Order ID"

AND Discount >= 0.25)

You can also rewrite this by using JOIN:

SELECT DISTINCT O."Order ID" FROM Orders O INNER JOIN "Order Details"

OD ON O."Order ID" = OD."Order ID" WHERE Discount >= 0.25

Limit Using Outer JOINs

  回复  引用    

2007-11-07 09:38 | ne[未注册用户]
IN的用法
Determines whether a given value matches any value in a subquery or a list.

Syntax

test_expression [ NOT ] IN
( subquery
| expression [ ,...n ]
)

Arguments
test_expression
Any valid expression in Microsoft SQL Server Compact 3.5.

subquery
A subquery that has a result set of one column. This column must have the same data type as test_expression.

expression [ ,... n]
A list of expressions to test for a match. All expressions must be of the same type as test_expression.

Result Types
bit

Return Value
If the value of test_expression is equal to any value returned by subquery, or is equal to any expression from the comma-separated list, then the return value is TRUE. Otherwise, the return value is FALSE.

Using NOT IN negates the returned value.

Example
The following example selects all customers in a table who are from Brazil, Argentina, and Venezuela.

Copy Code
SELECT * FROM Customers WHERE Country IN ('Brazil', 'Argentina', 'Venezuela')


  回复  引用    

2007-11-07 09:40 | ne[未注册用户]
EXIST 用法
Specifies a subquery to test for the existence of rows.

Syntax

EXISTS subquery

Arguments
subquery
A restricted SELECT statement.

Result Types
bit

Return Value
Returns TRUE if a subquery contains any rows.

Example
The following example finds all orders in the Orders table, with "Washington" as the Shipping Region, for each employee listed in the Employees table.

SELECT * FROM Orders WHERE [Ship Region] = 'WA' AND EXISTS (SELECT [Employee ID] FROM Employees AS Emp WHERE Emp.[Employee ID] = Orders.[Employee ID])

抱歉!评论已关闭.