ความแตกต่างระหว่างEXISTS
และIN
ข้อใน SQL คืออะไร?
เราควรใช้EXISTS
เมื่อใดและควรใช้เมื่อIN
ใด
ความแตกต่างระหว่างEXISTS
และIN
ข้อใน SQL คืออะไร?
เราควรใช้EXISTS
เมื่อใดและควรใช้เมื่อIN
ใด
คำตอบ:
exists
คำหลักที่สามารถนำมาใช้ในทางที่ แต่จริงๆก็ตั้งใจจะให้เป็นวิธีที่จะหลีกเลี่ยงการนับ:
--this statement needs to check the entire table
select count(*) from [table] where ...
--this statement is true as soon as one match is found
exists ( select * from [table] where ... )
สิ่งนี้มีประโยชน์มากที่สุดเมื่อคุณมีif
คำสั่งแบบมีเงื่อนไขซึ่งexists
อาจเร็วกว่าcount
มาก
in
จะใช้ดีที่สุดที่คุณมีรายการคงผ่าน:
select * from [table]
where [field] in (1, 2, 3)
เมื่อคุณมีตารางในin
คำสั่งมันเหมาะสมกว่าที่จะใช้ a join
แต่ส่วนใหญ่มันไม่สำคัญ เครื่องมือเพิ่มประสิทธิภาพการสืบค้นควรส่งคืนแผนเดียวกันด้วยวิธีใดวิธีหนึ่ง ในการใช้งานบางอย่าง (ส่วนใหญ่เก่ากว่าเช่น Microsoft SQL Server 2000) in
แบบสอบถามจะได้รับแผนการเข้าร่วมที่ซ้อนกันเสมอในขณะที่join
แบบสอบถามจะใช้ซ้อนกันผสานหรือแฮตามความเหมาะสม การใช้งานที่ทันสมัยกว่ามีความชาญฉลาดและสามารถปรับแผนได้แม้ในขณะที่in
ใช้งาน
select * from [table] where [field] in (select [field] from [table2])
ผลตอบแทนที่ได้ผลเหมือนกัน (และแผนแบบสอบถาม) select * from [table] join [table2] on [table2].[field] = [table].[field]
เช่น
table
ในขณะที่ผลตอบแทนทุกอย่างที่สองจากและtable
table2
ในฐานข้อมูล SQL (เก่ากว่าส่วนใหญ่) in
แบบสอบถามจะถูกนำไปใช้เป็นการเข้าร่วมที่ซ้อนกันในขณะที่join
แบบสอบถามสามารถซ้อนซ้อนผสานถูกแฮชและอื่น ๆ ได้เร็วที่สุด
exists
สามารถนำมาใช้ในคำสั่งกรณีดังนั้นพวกเขาจึงมีประโยชน์เช่นนั้นด้วยselect case when exists (select 1 from emp where salary > 1000) then 1 else 0 end as sal_over_1000
EXISTS
จะบอกคุณว่าแบบสอบถามส่งคืนผลลัพธ์ใด ๆ หรือไม่ เช่น:
SELECT *
FROM Orders o
WHERE EXISTS (
SELECT *
FROM Products p
WHERE p.ProductNumber = o.ProductNumber)
IN
ใช้เพื่อเปรียบเทียบหนึ่งค่ากับหลาย ๆ และสามารถใช้ค่าตามตัวอักษรเช่นนี้:
SELECT *
FROM Orders
WHERE ProductNumber IN (1, 10, 100)
นอกจากนี้คุณยังสามารถใช้ผลการสืบค้นด้วยส่วนIN
คำสั่งเช่นนี้:
SELECT *
FROM Orders
WHERE ProductNumber IN (
SELECT ProductNumber
FROM Products
WHERE ProductInventoryQuantity > 0)
ตามเครื่องมือเพิ่มประสิทธิภาพกฎ :
EXISTS
เร็วกว่าIN
เมื่อผลลัพธ์ของแบบสอบถามย่อยมีขนาดใหญ่มากIN
เร็วกว่าEXISTS
เมื่อผลลัพธ์แบบสอบถามย่อยมีขนาดเล็กมากตามเครื่องมือเพิ่มประสิทธิภาพต้นทุน :
ฉันสมมติว่าคุณรู้ว่าสิ่งที่พวกเขาทำและมีการใช้ที่แตกต่างกันดังนั้นฉันจะเข้าใจคำถามของคุณเป็น: เมื่อไหร่ควรเขียน SQL เพื่อใช้ IN แทน EXISTS หรือในทางกลับกัน
นั่นคือสมมติฐานที่ยุติธรรมหรือไม่?
แก้ไข : เหตุผลที่ฉันถามคือในหลาย ๆ กรณีคุณสามารถเขียน SQL โดยใช้ IN เพื่อใช้ EXISTS แทนและในทางกลับกันและสำหรับเอ็นจิ้นฐานข้อมูลบางตัวเครื่องมือเพิ่มประสิทธิภาพการสืบค้นจะปฏิบัติต่อทั้งสองอย่างแตกต่างกัน
ตัวอย่างเช่น
SELECT *
FROM Customers
WHERE EXISTS (
SELECT *
FROM Orders
WHERE Orders.CustomerID = Customers.ID
)
สามารถเขียนใหม่เป็น:
SELECT *
FROM Customers
WHERE ID IN (
SELECT CustomerID
FROM Orders
)
หรือด้วยการเข้าร่วม:
SELECT Customers.*
FROM Customers
INNER JOIN Orders ON Customers.ID = Orders.CustomerID
ดังนั้นคำถามของฉันยังคงมีอยู่คือโปสเตอร์ดั้งเดิมที่สงสัยเกี่ยวกับสิ่งที่ IN และ EXISTS ทำและวิธีการใช้หรือเขาขอให้เขียน SQL ที่ใช้ IN IN เพื่อใช้ EXISTS แทนหรือในทางกลับกันจะเป็นความคิดที่ดี?
JOIN
นั้นคุณจะต้องมีDISTINCT
EXISTS
เร็วกว่าIN
เมื่อผลลัพธ์ของแบบสอบถามย่อยมีขนาดใหญ่มาก
IN
จะเร็วกว่าEXISTS
เมื่อผลลัพธ์แบบสอบถามย่อยมีขนาดเล็กมาก
CREATE TABLE t1 (id INT, title VARCHAR(20), someIntCol INT)
GO
CREATE TABLE t2 (id INT, t1Id INT, someData VARCHAR(20))
GO
INSERT INTO t1
SELECT 1, 'title 1', 5 UNION ALL
SELECT 2, 'title 2', 5 UNION ALL
SELECT 3, 'title 3', 5 UNION ALL
SELECT 4, 'title 4', 5 UNION ALL
SELECT null, 'title 5', 5 UNION ALL
SELECT null, 'title 6', 5
INSERT INTO t2
SELECT 1, 1, 'data 1' UNION ALL
SELECT 2, 1, 'data 2' UNION ALL
SELECT 3, 2, 'data 3' UNION ALL
SELECT 4, 3, 'data 4' UNION ALL
SELECT 5, 3, 'data 5' UNION ALL
SELECT 6, 3, 'data 6' UNION ALL
SELECT 7, 4, 'data 7' UNION ALL
SELECT 8, null, 'data 8' UNION ALL
SELECT 9, 6, 'data 9' UNION ALL
SELECT 10, 6, 'data 10' UNION ALL
SELECT 11, 8, 'data 11'
แบบสอบถาม 1
SELECT
FROM t1
WHERE not EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id)
แบบสอบถาม 2
SELECT t1.*
FROM t1
WHERE t1.id not in (SELECT t2.t1id FROM t2 )
ถ้าในt1
id ของคุณมีค่า Null แล้ว Query 1 จะค้นหาพวกมัน แต่ Query 2 ไม่สามารถหาพารามิเตอร์ที่เป็น null ได้
ฉันหมายถึงIN
ไม่สามารถเปรียบเทียบอะไรกับ null ได้ดังนั้นมันจึงไม่มีผลลัพธ์สำหรับ null แต่EXISTS
สามารถเปรียบเทียบทุกอย่างกับ null ได้
หากคุณกำลังใช้IN
โอเปอเรเตอร์เครื่องยนต์ SQL จะสแกนเรคคอร์ดทั้งหมดที่ดึงมาจากเคียวรีด้านใน ในทางกลับกันถ้าเราใช้EXISTS
เครื่องมือ SQL จะหยุดกระบวนการสแกนทันทีที่พบการจับคู่
INสนับสนุนความสัมพันธ์ที่เท่าเทียมกันเท่านั้น (หรือความไม่เท่าเทียมกันเมื่อนำหน้าด้วยNOT )
มันเป็นคำพ้องที่จะ= ใด ๆ / = บางอย่างเช่น
select *
from t1
where x in (select x from t2)
;
EXISTSรองรับประเภทของความสัมพันธ์ที่หลากหลายซึ่งไม่สามารถแสดงได้โดยใช้INเช่น -
select *
from t1
where exists (select null
from t2
where t2.x=t1.x
and t2.y>t1.y
and t2.z like '℅' || t1.z || '℅'
)
;
ประสิทธิภาพที่ถูกกล่าวหาและความแตกต่างทางเทคนิคระหว่างEXISTSและINอาจเป็นผลมาจากการใช้งาน / ข้อ จำกัด / ข้อบกพร่องของผู้ขายที่เฉพาะเจาะจง แต่หลายครั้งพวกเขาไม่ใช่อะไรนอกจากตำนานที่ถูกสร้างขึ้น
คำจำกัดความของตารางความถูกต้องของสถิติการกำหนดค่าฐานข้อมูลและเวอร์ชันของเครื่องมือเพิ่มประสิทธิภาพนั้นมีผลกระทบต่อแผนการดำเนินการทั้งหมดและตามตัวชี้วัดประสิทธิภาพ
Exists
คำหลักประเมินจริงหรือเท็จ แต่IN
คำหลักเปรียบเทียบค่าทั้งหมดในคอลัมน์แบบสอบถามย่อยที่สอดคล้องกัน อีกอันหนึ่งSelect 1
สามารถใช้กับExists
คำสั่ง ตัวอย่าง:
SELECT * FROM Temp1 where exists(select 1 from Temp2 where conditions...)
แต่ IN
มีประสิทธิภาพน้อยลงExists
เร็วขึ้น
ฉันคิด,
EXISTS
คือเมื่อคุณต้องการจับคู่ผลลัพธ์ของแบบสอบถามกับแบบสอบถามย่อยอื่น คำค้นหา # 1 จำเป็นต้องดึงข้อมูลที่ตรงกับผลลัพธ์ของแบบสอบถามย่อย ชนิดของการเข้าร่วม .. เช่นเลือกลูกค้าตาราง # 1 ที่ได้วางตารางคำสั่งซื้อ # 2 ด้วย
IN คือการดึงข้อมูลหากค่าของคอลัมน์ที่ระบุนั้นอยู่IN
ในรายการ (1,2,3,4,5) เช่นเลือกลูกค้าที่อยู่ในรหัสไปรษณีย์ต่อไปนี้เช่นค่า zip_code อยู่ในรายการ (.... )
เมื่อใดควรใช้อีกตัวหนึ่ง ... เมื่อคุณรู้สึกว่าอ่านได้อย่างเหมาะสม (สื่อสารด้วยเจตนาที่ดีกว่า)
ความแตกต่างอยู่ที่นี่:
select *
from abcTable
where exists (select null)
แบบสอบถามด้านบนจะส่งคืนระเบียนทั้งหมดในขณะที่รายการด้านล่างจะส่งคืนค่าว่าง
select *
from abcTable
where abcTable_ID in (select null)
ลองดูและสังเกตผลลัพธ์
ตามความรู้ของฉันเมื่อแบบสอบถามย่อยผลตอบแทนคุ้มค่าแล้วคำสั่งทั้งหมดจะกลายเป็นNULL
NULL
ในกรณีนี้เราใช้EXITS
คำหลัก หากเราต้องการเปรียบเทียบค่าเฉพาะในแบบสอบถามย่อยเราจะใช้IN
คำหลัก
อันที่เร็วกว่านั้นขึ้นอยู่กับจำนวนการสืบค้นที่สืบค้นโดยการสืบค้นภายใน:
มีอยู่ประเมินบนจริงหรือเท็จ แต่ในการเปรียบเทียบค่าหลายค่า เมื่อคุณไม่ทราบว่ามีระเบียนอยู่หรือไม่คุณควรเลือกมีอยู่
เหตุผลก็คือผู้ประกอบการ EXISTS ทำงานตามหลักการ“ อย่างน้อยพบ” มันจะคืนค่าจริงและหยุดสแกนตารางหนึ่งครั้งอย่างน้อยหนึ่งแถวที่พบ
ในทางกลับกันเมื่อตัวดำเนินการ IN รวมกับแบบสอบถามย่อย MySQL จะต้องประมวลผลแบบสอบถามย่อยก่อนแล้วจึงใช้ผลลัพธ์ของแบบสอบถามย่อยเพื่อประมวลผลแบบสอบถามทั้งหมด
กฎทั่วไปของหัวแม่มือคือถ้าแบบสอบถามย่อยมีข้อมูลจำนวนมากผู้ประกอบการ EXISTS จะให้ประสิทธิภาพที่ดีกว่า
อย่างไรก็ตามแบบสอบถามที่ใช้ตัวดำเนินการ IN จะทำงานได้เร็วขึ้นหากชุดผลลัพธ์ที่ส่งคืนจากแบบสอบถามย่อยมีขนาดเล็กมาก
ความเข้าใจของฉันคือทั้งคู่ควรจะเหมือนกันตราบใดที่เราไม่ได้เกี่ยวข้องกับค่า NULL
เหตุผลเดียวกันกับที่เคียวรีไม่ส่งคืนค่าสำหรับ = NULL vs คือ NULL http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/
ในฐานะที่เป็นอาร์กิวเมนต์บูลีน vs comparator ไปเพื่อสร้างบูลีนทั้งสองค่าจะต้องมีการเปรียบเทียบและนั่นคือวิธีการใด ๆ ถ้าเงื่อนไขใช้งานได้ดังนั้นฉันล้มเหลวที่จะเข้าใจว่า IN และ EXISTS ทำงานอย่างไรแตกต่างกัน
In certain circumstances, it is better to use IN rather than EXISTS. In general, if the selective predicate is in the subquery, then use IN. If the selective predicate is in the parent query, then use EXISTS.
https://docs.oracle.com/cd/B19306_01/server.102/b14211/sql_1016.htm#i28403
หากเคียวรีย่อยส่งคืนมากกว่าหนึ่งค่าคุณอาจต้องดำเนินการเคียวรีภายนอก - ถ้าค่าภายในคอลัมน์ที่ระบุในเงื่อนไขตรงกับค่าใด ๆ ในชุดผลลัพธ์ของเคียวรีย่อย ในการทำงานนี้คุณต้องใช้in
คำหลัก
คุณสามารถใช้แบบสอบถามย่อยเพื่อตรวจสอบว่ามีชุดของระเบียนอยู่หรือไม่ สำหรับสิ่งนี้คุณต้องใช้ส่วนexists
คำสั่งย่อยด้วยแบบสอบถาม exists
คำหลักเสมอกลับค่าจริงหรือเท็จ
ฉันเชื่อว่านี่เป็นคำตอบที่ตรงไปตรงมา ทำไมคุณไม่ตรวจสอบจากคนที่พัฒนาฟังก์ชั่นนั้นในระบบของพวกเขา?
หากคุณเป็นนักพัฒนา MS SQL นี่คือคำตอบโดยตรงจาก Microsoft
IN
:
กำหนดว่าค่าที่ระบุตรงกับค่าใด ๆ ในแบบสอบถามย่อยหรือรายการ
ระบุเคียวรีย่อยเพื่อทดสอบการมีอยู่ของแถว
ฉันพบว่าการใช้คำหลัก EXISTS มักจะช้ามาก (นั่นเป็นเรื่องจริงใน Microsoft Access) ฉันแทนที่จะใช้โอเปอเรเตอร์การรวมในลักษณะนี้: should-i-use-the-keyword-exist-in-sql
EXISTS ทำงานได้เร็วขึ้นกว่าใน หากเกณฑ์ตัวกรองส่วนใหญ่อยู่ในแบบสอบถามย่อยควรใช้ IN และดีกว่าหากเกณฑ์ตัวกรองส่วนใหญ่อยู่ในแบบสอบถามหลักให้ใช้ EXISTS ได้ดีกว่า
หากคุณใช้ตัวดำเนินการ IN โปรแกรม SQL จะสแกนระเบียนทั้งหมดที่ดึงมาจากแบบสอบถามภายใน ในทางตรงกันข้ามถ้าเราใช้ EXISTS เอ็นจิน SQL จะหยุดกระบวนการสแกนทันทีที่พบการจับคู่
IN
และEXISTS
สามารถเทียบเท่าและแปรสภาพเป็นกันและกัน
JOIN
IN