การใช้งานฐานข้อมูลของ ORDER BY ในแบบสอบถามย่อย


10

ฉันกำลังใช้แอปพลิเคชัน (MapServer - http://mapserver.org/ ) ที่ล้อมรอบคำสั่ง SQL เพื่อให้คำสั่ง ORDER BY อยู่ในแบบสอบถามภายใน เช่น

SELECT * FROM (
        SELECT ID, GEOM, Name
        FROM t
        ORDER BY Name
        ) as tbl

แอปพลิเคชันมีไดรเวอร์ฐานข้อมูลที่แตกต่างกันมากมาย ฉันใช้ไดรเวอร์ MS SQL Server เป็นหลักและ SQL Server 2008 ส่วนใหญ่จะเกิดข้อผิดพลาดหากพบคำสั่งซื้อในแบบสอบถามย่อย

จาก MS Docs (แม้ว่าจะใช้กับ SQL Server 2000 แต่ก็ดูเหมือนว่าจะใช้):

เมื่อคุณใช้ส่วนคำสั่ง ORDER BY ในมุมมองฟังก์ชั่นอินไลน์ตารางที่ได้รับหรือแบบสอบถามย่อยมันไม่รับประกันผลลัพธ์ที่สั่งซื้อ แต่คำสั่งย่อย ORDER BY ใช้เพื่อรับประกันว่าชุดผลลัพธ์ที่สร้างขึ้นโดยผู้ดำเนินการด้านบนเท่านั้นที่มีการแต่งหน้าที่สอดคล้องกัน ส่วนคำสั่ง ORDER BY รับประกันเฉพาะชุดผลลัพธ์ที่ได้รับคำสั่งเมื่อมีการระบุไว้ในคำสั่ง SELECT ที่อยู่นอกสุด

อย่างไรก็ตามแบบสอบถามชนิดเดียวกันเมื่อเรียกใช้ใน Postgres (9) และ Oracle ส่งคืนผลลัพธ์ - โดยมีลำดับตามที่กำหนดไว้ในแบบสอบถามย่อย ใน Postgres แผนแบบสอบถามจะแสดงผลลัพธ์จะถูกจัดเรียงและบันทึกการออกรุ่นของ Postgres จะรวมรายการที่ใช้คำสั่งแบบสอบถามย่อย:

หลีกเลี่ยงการเรียงลำดับเมื่อแบบสอบถามย่อย ORDER BY จับคู่แบบสอบถามบน

http://en.wikipedia.org/wiki/Order_byกล่าวว่า:

แม้ว่าระบบฐานข้อมูลบางระบบจะอนุญาตให้ระบุข้อกำหนดของคำสั่งย่อย ORDER BY ในการเลือกย่อยหรือดูคำจำกัดความการมีอยู่ไม่มีผลใด ๆ

อย่างไรก็ตามจากการตรวจสอบแผนแบบสอบถามของฉันเอง:

  • SQL Server 2008 ไม่สนับสนุน ORDER BY ในแบบสอบถามย่อย
  • Postgres 9 รองรับ ORDER BY ในแบบสอบถามย่อย
  • Oracle 10g รองรับ ORDER BY ในแบบสอบถามย่อย

ดังนั้นคำถามของฉันมีลิงก์ใด ๆ ที่สามารถยืนยันหรือปฏิเสธได้อย่างเป็นทางการว่า Postgres และ Oracle ไม่อนุญาตให้เรียงลำดับในแบบสอบถามย่อย?


2
เพียงเพราะคุณสังเกตเห็นผลลัพธ์บางอย่างไม่ได้รับประกัน หากคุณต้องการความมั่นคงให้วางคำสั่งซื้อไว้ด้านนอก ระยะเวลา
Aaron Bertrand

อุดมคตินี้คือสิ่งที่จะดำเนินการ อย่างไรก็ตามการเข้าสู่ขั้นตอนนี้จะเกี่ยวข้องกับการเปลี่ยนแปลงในตรรกะหลักและไดรเวอร์ฐานข้อมูลจำนวนมาก เนื่องจากปัญหานี้ยังไม่ได้รับการรายงานในหลายปีที่ผ่านมาดูเหมือนว่าบางคนใช้วิธีการสั่งซื้ออย่างต่อเนื่องในแบบสอบถามย่อย มันคงจะดีถ้าได้รู้ว่าอันไหนเป็นไปได้
geographika

2
@geographika แม้ว่า DBMS บางตัวจะทำอย่างสม่ำเสมอมาจนถึงตอนนี้ก็ไม่มีอะไรรับประกันได้ว่าพวกเขาจะทำเช่นเดียวกันในอนาคต ตัวอย่างเช่นการปรับปรุง MySQL ของเครื่องมือเพิ่มประสิทธิภาพใน 5.6 (และ MariaDB 5.3) จะระบุว่าORDER BYในแบบสอบถามย่อยนั้นซ้ำซ้อนและไม่ทำการเรียงลำดับที่ไม่จำเป็น
ypercubeᵀᴹ

คำตอบ:


15

คุณจะต้องทำให้แอปพลิเคชันของคุณไม่วางORDER BYอยู่ข้างในแบบสอบถามย่อย (อาจมีตัวเลือกที่จะไม่ใช้แบบสอบถามย่อยที่ไม่มีความจำเป็นในตอนแรก) ในขณะที่คุณได้ค้นพบแล้วรูปแบบนี้จะไม่ได้รับการสนับสนุนใน SQL Server TOPโดยไม่ต้อง และด้วยTOP, ถ้าคุณไม่ต้องการที่จะปล่อยแถว, การใช้TOP 100 PERCENTจะทำให้การORDER BYเพิ่มประสิทธิภาพออกไป.

และใน Oracle และ PostGres เพียงเพราะมีการสนับสนุนไวยากรณ์ไม่ได้หมายความว่ามันจะเชื่อฟัง และเพียงเพราะคุณสังเกตว่ามันถูกเชื่อฟังในบางสถานการณ์ไม่ได้หมายความว่ามันจะยังคงเชื่อฟังต่อไปเมื่อเวอร์ชันใหม่ออกมาหรือมีการเปลี่ยนแปลงเล็กน้อยในข้อมูลสถิติแบบสอบถามของตัวเองหรือสภาพแวดล้อม

ฉันสามารถมั่นใจได้ว่าไม่ต้องสงสัยถ้าคุณต้องการการรับประกันเกี่ยวกับคำสั่งคุณจะต้องใส่ORDER BYในแบบสอบถามนอกสุด นี่ควรเป็นหลักคำสอนที่คุณยึดถือไว้ไม่ว่าคุณจะใช้แพลตฟอร์มใด

คุณกำลังขอลิงค์ที่ระบุอย่างเป็นทางการว่ามีบางอย่างที่ไม่รองรับ นี่เหมือนกับการดูในคู่มือเจ้าของรถของคุณเพื่อรับแถลงการณ์อย่างเป็นทางการว่ารถของคุณไม่สามารถบินได้


ขอบคุณ ฉันคิดว่า MSSQL มีแนวทางที่ถูกต้องในการขว้างข้อผิดพลาด ทั้งสนับสนุนและดำเนินการเรียงลำดับตามการสืบค้นภายในเมื่อเทียบกับหลักการ SQL หลักดูเหมือนว่าสูตรสำหรับภัยพิบัติ ไม่แน่ใจเกี่ยวกับการเปรียบเทียบรถ - คุณต้องเพิ่มการค้นหาในคู่มือในขณะที่รถกำลังบินจริง ..
geographika

-1

ฉันยอมรับว่ามันไม่น่าเชื่อ แต่ถ้าคุณกำลังเหน็บแนมลองส่งกลับจำนวนแถวสูงสุดในแบบสอบถามย่อย การส่งคืน 100 เปอร์เซ็นต์แรกสุดจะไม่ทำงาน แต่ถ้าคุณต้องการแก้ไขปัญหาคุณสามารถสอบถามจำนวนแถวและส่งต่อไปที่ TOP เป็นตัวแปร ฉันทดสอบสิ่งนี้ในฐานข้อมูลที่ตั้งค่าเป็นความเข้ากันได้ระดับ 80 ดังนั้นฉันคิดว่ามันควรจะทำงานกับ SQL 2000

SELECT * FROM (
        SELECT TOP (100000) ID, GEOM, Name
        FROM t
        ORDER BY Name
        ) as tbl

ฉันได้ลองทำสิ่งนี้ในตอนแรกและดูเหมือนว่าจะเรียงลำดับได้ดีสำหรับชุดข้อมูลขนาดเล็ก อย่างไรก็ตามเมื่อฉันได้รับชุดระเบียนที่มีขนาดใหญ่มากการเรียงลำดับกลายเป็นแบบสุ่มอีกครั้งใน SQL Server 2008R2 อาจเกี่ยวข้องกับขนาดหน่วยความจำ / หน้า?
geographika

ขออภัยมันไม่ได้ช่วย การเลือก 100 เปอร์เซ็นต์แรกสุดจะทำให้การเรียงลำดับกลับไปเป็นแบบสุ่ม
DBNull

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