Sql 写带有“QUOTE”的select语句最有效的方法是什么;不在「;子查询?
编写类似以下内容的select语句的最有效方法是什么Sql 写带有“QUOTE”的select语句最有效的方法是什么;不在「;子查询?,sql,sql-server,tsql,Sql,Sql Server,Tsql,编写类似以下内容的select语句的最有效方法是什么 SELECT * FROM Orders WHERE Orders.Order_ID not in (Select Order_ID FROM HeldOrders) 要点是当项目不在另一个表中时,您需要一个表中的记录。您可以使用左外部联接并检查右表上的NULL SELECT O1.* FROM Orders O1 LEFT OUTER JOIN HeldOrders O2 ON O1.Order_ID = O2.Order_Id WHER
SELECT *
FROM Orders
WHERE Orders.Order_ID not in (Select Order_ID FROM HeldOrders)
要点是当项目不在另一个表中时,您需要一个表中的记录。您可以使用
左外部联接
并检查右表上的NULL
SELECT O1.*
FROM Orders O1
LEFT OUTER JOIN HeldOrders O2
ON O1.Order_ID = O2.Order_Id
WHERE O2.Order_Id IS NULL
首先,我的博客中有一篇关于
notin
谓词如何在sqlserver
中(以及在其他系统中)工作的老文章的链接:
您可以按如下方式重写它:
SELECT *
FROM Orders o
WHERE NOT EXISTS
(
SELECT NULL
FROM HeldOrders ho
WHERE ho.OrderID = o.OrderID
)
但是,大多数数据库将以相同的方式处理这些查询
这两个查询都将使用某种类型的反连接
如果要检查两列或更多列,这对于SQL Server
非常有用,因为SQL Server
不支持以下语法:
SELECT *
FROM Orders o
WHERE (col1, col2) NOT IN
(
SELECT col1, col2
FROM HeldOrders ho
)
但是,请注意,不在
中可能会比较棘手,因为它处理NULL
值的方式不同
如果hold.Orders
可为空,则未找到任何记录,子查询只返回一个NULL
,整个查询将不返回任何内容(在这种情况下,中的和不在中的将计算为NULL
)
考虑这些数据:
Orders:
OrderID
---
1
HeldOrders:
OrderID
---
2
NULL
此查询:
SELECT *
FROM Orders o
WHERE OrderID NOT IN
(
SELECT OrderID
FROM HeldOrders ho
)
SELECT *
FROM Orders o
LEFT JOIN
HeldOrders ho
ON ho.OrderID = o.OrderID
WHERE ho.OrderID IS NULL
将不返回任何内容,这可能不是您所期望的
然而,这一点:
SELECT *
FROM Orders o
WHERE NOT EXISTS
(
SELECT NULL
FROM HeldOrders ho
WHERE ho.OrderID = o.OrderID
)
将返回带有OrderID=1
的行
请注意,其他人提出的LEFT JOIN
解决方案远不是最有效的解决方案
此查询:
SELECT *
FROM Orders o
WHERE OrderID NOT IN
(
SELECT OrderID
FROM HeldOrders ho
)
SELECT *
FROM Orders o
LEFT JOIN
HeldOrders ho
ON ho.OrderID = o.OrderID
WHERE ho.OrderID IS NULL
将使用一个筛选条件,该条件需要计算并筛选出所有匹配的行,这些行可以是numerius
中的和存在的使用的反连接方法只需确保订单中每行不存在一条记录,因此它将首先消除所有可能的重复:
嵌套循环反连接
和合并反连接
在计算直升机时只会跳过重复项
- 在构建哈希表时,
哈希反联接
将消除重复项
我不确定什么是最有效的,但其他选项包括:
1. Use EXISTS
SELECT *
FROM ORDERS O
WHERE NOT EXISTS (SELECT 1
FROM HeldOrders HO
WHERE O.Order_ID = HO.OrderID)
2. Use EXCEPT
SELECT O.Order_ID
FROM ORDERS O
EXCEPT
SELECT HO.Order_ID
FROM HeldOrders
试一试
根据表的大小、索引等,“最有效”将有所不同。换句话说,它将根据您使用的具体情况而有所不同
根据具体情况,我通常使用三种方法来实现您的目标
1。如果Orders.order\u id已编入索引,且HeldOrders相当小,则您的示例效果良好。
SELECT *
FROM Orders o
WHERE Orders.Order_ID not in (Select Order_ID
FROM HeldOrders h
where h.order_id = o.order_id)
SELECT *
FROM Orders o
left outer join HeldOrders h on h.order_id = o.order_id
where h.order_id is null
2。另一种方法是“相关子查询”,它是对您所拥有内容的一个细微变化…
SELECT *
FROM Orders o
WHERE Orders.Order_ID not in (Select Order_ID
FROM HeldOrders h
where h.order_id = o.order_id)
SELECT *
FROM Orders o
left outer join HeldOrders h on h.order_id = o.order_id
where h.order_id is null
注意添加了where子句。当HeldOrders有大量行时,这种方法的效果会更好。订单ID需要在两个表中建立索引
3。我有时使用的另一种方法是左外连接…
SELECT *
FROM Orders o
WHERE Orders.Order_ID not in (Select Order_ID
FROM HeldOrders h
where h.order_id = o.order_id)
SELECT *
FROM Orders o
left outer join HeldOrders h on h.order_id = o.order_id
where h.order_id is null
使用左外部联接时,当存在匹配行时,h.order\U id中的值将与o.order\U id匹配。如果没有匹配的行,h.order\U id将为空。通过检查where子句中的NULL值,您可以过滤所有不匹配的内容
这些变体中的每一种都可以在不同的场景中或多或少地发挥作用。最好的方法是尝试各种方法并检查执行计划。在我的情况下,SQL Server 2000中,考虑到相关表的索引,“联接”查询是最快的。SELECT*FROM Orders o LEFT JOIN HeldOrders h on o.Order_ID=h.Order_ID且h.Order_ID为空这远不是最有效的方法。这不一定是最有效的方法。它比子查询效率要高很多,尽管-至少它只对第二个表执行一次,而不是一次/行。@rwmnau
:是什么让您认为第二个查询将被多次执行?我得到纠正-一个小小的Control-L操作已经为我证实了这一点。我的想法是WHERE子句中的任何内容总是每行执行一次,但似乎我错了。我想确定它的最佳方法是经常检查执行计划。@Dave
:为什么在方法2
中使用NOT EXISTS
而不是NOT EXISTS
。在阅读了上面的答案后,我计划开始使用NOT EXISTS。选项3在我的方案中效果最好(SQL Server 2000给出了我的表索引)。我认为最好的答案是测试一些方法。这里有一篇有趣的文章()比较了连接
,中的和存在之间的逻辑差异,这是我第一次看到一个相关子查询,它实际上需要一个相关子查询,我可以在不到5分钟的时间内摸索。希望我几年前就知道这个技巧。在本节中,您是什么意思:“如果您想检查两列或更多列,这对SQL Server很有用,因为SQL Server不支持此语法:”。你是说这不适用于SQL Server吗?你错过了一个“不”?@Stimy
:当然,我错过了一个不
SQL Server
与Oracle
不同,MySQL
和PostgreSQL
在in
/not in
谓词中不支持多个列。在相关子查询中使用not EXISTS,而不是像我一直做的那样通过外部联接(特别是对于多列查找)。