IN เทียบกับตัวดำเนินการใด ๆ ใน PostgreSQL


119

ความแตกต่างระหว่างINและANYตัวดำเนินการใน PostgreSQL คืออะไร?
กลไกการทำงานของทั้งสองดูเหมือนจะเหมือนกัน ใครช่วยอธิบายเรื่องนี้ด้วยตัวอย่างได้ไหม


3
อาจซ้ำกันของpostgreSQL - in vs any
Vivek S.

สิ่งนี้ตอบคำถามของคุณหรือไม่? ความแตกต่างระหว่าง in และตัวดำเนินการใด ๆ ใน sql
philipxy

คำตอบ:


158

(ทั้งINมิได้ANYเป็น "ผู้ประกอบการ". A "สร้าง" หรือ "องค์ประกอบไวยากรณ์".)

เหตุผลโดยอ้างถึงคู่มือ :

INเทียบเท่ากับ= ANY.

แต่มีสองสายพันธุ์ไวยากรณ์ของสองสายพันธุ์IN ANYรายละเอียด:

IN การเซ็ตจะเทียบเท่ากับ= ANYการเซ็ตตามที่แสดงไว้ที่นี่:

แต่ตัวแปรที่สองของแต่ละตัวไม่เทียบเท่ากับตัวแปรอื่น ตัวแปรที่สองของการANYสร้างใช้เวลาอาร์เรย์ (ต้องเป็นชนิดอาร์เรย์ที่เกิดขึ้นจริง) ในขณะที่ตัวแปรที่สองของการINใช้คั่นด้วยเครื่องหมายจุลภาครายการค่า สิ่งนี้นำไปสู่ข้อ จำกัด ที่แตกต่างกันในการส่งผ่านค่าและยังสามารถนำไปสู่แผนการสืบค้นที่แตกต่างกันในกรณีพิเศษ:

ANY มีความหลากหลายมากขึ้น

ANYสร้างอยู่ไกลมากขึ้นหลากหลายขณะที่มันสามารถใช้ร่วมกับผู้ประกอบการต่าง ๆ =ไม่ได้เป็นเพียง ตัวอย่าง:

SELECT 'foo' LIKE ANY('{FOO,bar,%oo%}');

สำหรับค่าจำนวนมากให้จัดชุดสเกลที่ดีกว่าสำหรับแต่ละค่า:

ที่เกี่ยวข้อง:

การผกผัน / ตรงกันข้าม / การยกเว้น

"ค้นหาแถวที่idอยู่ในอาร์เรย์ที่กำหนด":

SELECT * FROM tbl WHERE id = ANY (ARRAY[1, 2]);

ผกผัน: "หาแถวที่idเป็นไม่ได้ในอาร์เรย์":

SELECT * FROM tbl WHERE id <> ALL (ARRAY[1, 2]);
SELECT * FROM tbl WHERE id <> ALL ('{1, 2}');  -- equivalent array literal
SELECT * FROM tbl WHERE NOT (id = ANY ('{1, 2}'));

เทียบเท่าทั้งสาม ครั้งแรกกับคอนสตรัคอาร์เรย์อีกสองกับอาร์เรย์ที่แท้จริง ชนิดข้อมูลได้มาจากบริบทอย่างไม่น่าสงสัย '{1,2}'::int[]อื่นหล่ออย่างชัดเจนอาจจะต้องชอบ

แถวที่มีid IS NULLไม่ผ่านนิพจน์เหล่านี้ หากต้องการรวมNULLค่าเพิ่มเติม:

SELECT * FROM tbl WHERE (id = ANY ('{1, 2}')) IS NOT TRUE;

4
เป็นการดีที่จะชี้แจงอย่างชัดเจนว่าผลลัพธ์ของตัวแปรที่สองจะเหมือนกันเสมอ ฉันแน่ใจ 99% ว่าเป็นเช่นนั้นจริง แต่คำตอบดูเหมือนจะไม่ระบุ ความหมายที่SELECT * from mytable where id in (1, 2, 3)จะส่งผลให้แถวเดียวกันเสมอSELECT * from mytable where id = ANY('{1, 2, 3}')แม้ว่าอาจมีแผนการสืบค้นที่แตกต่างกันก็ตาม
KPD

1
ANY ไม่สามารถใช้ร่วมกับตัว!=ดำเนินการได้ ผมไม่คิดว่ามันเป็นเอกสาร แต่ไม่ได้เช่นเดียวกับselect * from foo where id != ANY (ARRAY[1, 2]) select * from foo where id NOT IN (1, 2)ในทางกลับกันselect * from foo where NOT (id = ANY (ARRAY[1, 2]))ทำงานตามที่คาดไว้
qris

1
@qris: ANYสามารถใช้ร่วมกับตัว!=ดำเนินการได้ แต่มีมากกว่านั้น ฉันเพิ่มบทด้านบน (โปรดทราบว่า<>เป็นตัวดำเนินการใน SQL มาตรฐาน - แม้ว่า!=จะได้รับการยอมรับเช่นกันใน Postgres)
Erwin Brandstetter

เวอร์ชันล่าสุดที่มีNULLค่าต่างๆทำงานอย่างไร จะWHERE id = ANY (ARRAY[1, 2]) OR id IS NULL;ทำงานได้ดีหรือไม่?
dvtan

1
@dvtan: ใช้(id = ...) IS NOT TRUEงานได้เพราะid = ...จะประเมินTRUEว่ามีการแข่งขันจริงหรือไม่ ผลลัพธ์FALSEหรือNULLผ่านการทดสอบของเรา ดู: stackoverflow.com/a/23767625/939860 นิพจน์ที่คุณเพิ่มจะทดสอบอย่างอื่น สิ่งนี้จะเทียบเท่าWHERE id <> ALL (ARRAY[1, 2]) OR id IS NULL;
Erwin Brandstetter

3

มีสองประเด็นที่ชัดเจนเช่นเดียวกับประเด็นในคำตอบอื่น ๆ :

  • เทียบเท่ากันทุกประการเมื่อใช้แบบสอบถามย่อย:

    SELECT * FROM table
    WHERE column IN(subquery);
    
    SELECT * FROM table
    WHERE column = ANY(subquery);

ในทางกลับกัน:

  • เฉพาะINโอเปอเรเตอร์เท่านั้นที่อนุญาตรายการง่ายๆ:

    SELECT * FROM table
    WHERE column IN(… ,  , …);

การสันนิษฐานว่าพวกเขาเหมือนกันทำให้ฉันหลงลืมหลายครั้งเมื่อลืมสิ่งนั้นANYไม่ได้ผลกับรายการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.