ฉันจะทำให้คิวรี SQL ที่ซับซ้อนเขียนง่ายขึ้นได้อย่างไร [ปิด]


42

ฉันพบว่ามันยากมากที่จะเขียนแบบสอบถาม SQL ที่ซับซ้อนที่เกี่ยวข้องกับการรวมในหลาย ๆ ตาราง (อย่างน้อย 3-4) และเกี่ยวข้องกับเงื่อนไขซ้อนหลาย ข้อความค้นหาที่ฉันถูกขอให้เขียนนั้นอธิบายได้ง่ายด้วยประโยคสองสามประโยค แต่อาจต้องใช้รหัสที่หลอกลวง ฉันค้นหาตัวเองบ่อยครั้งโดยใช้มุมมองชั่วคราวเพื่อเขียนข้อความค้นหาเหล่านี้ซึ่งดูเหมือนว่าเป็นเรื่องเล็ก ๆ น้อย ๆ คุณสามารถให้เคล็ดลับใดที่ฉันสามารถใช้เพื่อทำให้การสืบค้นที่ซับซ้อนเหล่านี้ง่ายขึ้น โดยเฉพาะอย่างยิ่งฉันจะแยกแบบสอบถามเหล่านี้ออกเป็นขั้นตอนที่ฉันต้องใช้เพื่อเขียนรหัส SQL ได้อย่างไร

โปรดทราบว่าฉันเป็น SQL ฉันกำลังถูกขอให้เขียนเป็นส่วนหนึ่งของการบ้านสำหรับหลักสูตรฐานข้อมูลดังนั้นฉันไม่ต้องการซอฟต์แวร์ที่จะทำงานให้ฉัน ฉันต้องการเข้าใจรหัสที่ฉันเขียน

รายละเอียดทางเทคนิคเพิ่มเติม:

  • ฐานข้อมูลโฮสต์บนเซิร์ฟเวอร์ PostgreSQL ที่รันบนเครื่องโลคัล
  • ฐานข้อมูลมีขนาดเล็กมาก: มีไม่เกินเจ็ดตารางและตารางที่ใหญ่ที่สุดมีน้อยกว่าประมาณ 50 แถว
  • เคียวรี SQL กำลังถูกส่งผ่านไปยังเซิร์ฟเวอร์โดยผ่าน LibreOffice Base

จริง ๆ แล้วมุมมองชั่วคราวนั้นมีประโยชน์มากเพราะคุณสามารถทำสิ่งต่าง ๆ ในตาราง (เช่นดัชนีที่ซับซ้อนอย่างชัดเจน) ซึ่งยากมากที่จะบอกใบ้ถึงตัวแยกวิเคราะห์ SQL

โดยส่วนตัวแล้วฉันพบว่ามันง่ายกว่าที่จะโกงโดยใช้ GUI (เช่นฐาน LibreOffice "สร้างแบบสอบถามในมุมมองออกแบบ" หรือ Office Access "สร้าง"> "ออกแบบแบบสอบถาม") แล้วดู SQL ที่สร้าง บางครั้งมีความจำเป็นต้องปรับเปลี่ยน SQL ที่กำหนดโดยตัวออกแบบ GUI แต่ให้จุดเริ่มต้นที่ดี
kurdtpage

คำตอบ:


49

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

ทำความเข้าใจกับความสัมพันธ์ของตาราง - ส่วนใหญ่จะเป็นแบบหนึ่งต่อหลาย รู้ตาราง "จำนวนมาก" ระบุฟิลด์ที่จำเป็นสำหรับการเข้าร่วมของคุณ

คิดเกี่ยวกับสถานการณ์เข้าร่วม LEFT - เลือกพนักงานทั้งหมดและเงินเดือนของพวกเขาจากเดือนที่แล้ว เกิดอะไรขึ้นถ้าพวกเขาไม่ได้รับเงินเดือนเมื่อเดือนที่แล้ว?

รู้ชุดผลลัพธ์: 1) ในสเปรดชีตป้อนระเบียนที่ถูกต้องอย่างน้อยหนึ่งรายการสำหรับแบบสอบถามของคุณด้วยตนเอง 2) เขียนแบบสอบถามในรูปแบบที่ง่ายพอที่จะระบุจำนวนระเบียนที่ควรจะถูกส่งกลับ ใช้ทั้งสองอย่างนี้เพื่อทดสอบการค้นหาของคุณเพื่อให้แน่ใจว่าการเข้าร่วมตารางใหม่จะไม่เปลี่ยนแปลงผลลัพธ์

แยกแบบสอบถามของคุณออกเป็นส่วนที่จัดการได้ - คุณไม่จำเป็นต้องเขียนทั้งหมดในครั้งเดียว บางครั้งแบบสอบถามที่ซับซ้อนอาจเป็นเพียงชุดของแบบสอบถามแบบง่าย

ระวังการรวมระดับต่าง ๆ : หากคุณต้องใส่ค่ารายเดือนรายไตรมาสและรายปีในชุดผลลัพธ์เดียวกันคุณจะต้องคำนวณแยกต่างหากในแบบสอบถามที่จัดกลุ่มตามค่าที่แตกต่างกัน

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

สูตรซับซ้อน / ซ้อนกัน - พยายามเยื้องสม่ำเสมอและอย่ากลัวที่จะใช้หลายบรรทัด "กรณีเมื่อกรณีเมื่อกรณี" จะผลักดันคุณถั่ว ใช้เวลาในการคิดสิ่งเหล่านี้ผ่าน บันทึก calcs ที่ซับซ้อนเป็นครั้งสุดท้าย รับการบันทึกที่ถูกต้องที่เลือกก่อน จากนั้นคุณโจมตีสูตรที่ซับซ้อนซึ่งรู้ว่าคุณกำลังทำงานกับค่าที่เหมาะสม การเห็นค่าที่ใช้ในสูตรจะช่วยให้คุณมองเห็นบริเวณที่คุณต้องคำนึงถึงค่า NULL และตำแหน่งที่จะจัดการหารด้วยศูนย์ข้อผิดพลาด

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


1
สิ่งที่ยอดเยี่ยมจริงๆ ฉันต้องการเน้นย้ำถึงจุดของเจฟฟ์ในการมองหา LEFT ร่วมและแยกคิวรีที่ซับซ้อนเป็นขนาดเล็กจัดการได้มากขึ้นแล้วรวมพวกเขา ฉันเขียนข้อความค้นหาขนาดใหญ่บนฐานข้อมูลขนาดใหญ่ทุกวันโดยเฉพาะอย่างยิ่งสิ่งที่เกิดขึ้นตลอดเวลา เรียกใช้แบบสอบถามและแบบสอบถามย่อยเสมอโดยเร็วที่สุดเพื่อให้แน่ใจว่าคุณได้รับข้อมูลที่คุณคาดว่าจะเห็นในแต่ละขั้นตอน
CodexArcanum

@CodexArcanum - และเมื่อคุณเรียกใช้คิวรีกับข้อมูลขนาดใหญ่มันไม่เจ็บเลยที่จะใช้ TOP;)
JeffO

ฉันเห็นด้วยกับทุกคำแนะนำของคุณ
อเลสซานโดรรอสซี

28
  1. การเยื้องจะเป็นสิ่งแรกที่ต้องทำหากคุณยังไม่ได้ทำ ไม่เพียง แต่มันจะมีประโยชน์กับคำสั่งง่าย ๆ แม้ select top 1 [ColumnName] from [TableName]แต่มันเป็นสิ่งสำคัญเมื่อมันมาถึงการเข้าร่วมและแบบสอบถามบิตซับซ้อนมากขึ้นกว่า

  2. เยื้องครั้งอย่างถูกต้องไม่มีอะไรห้ามการเพิ่มความคิดเห็นภายในแบบสอบถามตัวเองตามความเหมาะสม อย่าใช้มากเกินไป: หากรหัสชัดเจนเพียงพอการเพิ่มความคิดเห็นจะเป็นอันตรายต่อความชัดเจนของรหัส แต่พวกเขายังยินดีสำหรับส่วนที่ชัดเจนน้อยกว่าของแบบสอบถาม

    โปรดทราบว่าข้อความค้นหาที่ยาวขึ้น (รวมถึงข้อความค้นหาที่มีความคิดเห็น) จะหมายถึงการใช้แบนด์วิดท์ที่ใหญ่ขึ้นระหว่างแอพพลิเคชันเซิร์ฟเวอร์และเซิร์ฟเวอร์ฐานข้อมูลของคุณ นอกจากนี้โปรดทราบว่าหากคุณกำลังทำงานกับผลิตภัณฑ์ระดับ Google ด้วยคำขอจำนวนมากต่อวินาทีซึ่งต้องการประสิทธิภาพที่ยอดเยี่ยมและการใช้ทรัพยากรขนาดที่เพิ่มโดยความคิดเห็นอาจไม่เปลี่ยนแปลงอะไรสำหรับคุณในแง่ของประสิทธิภาพ

  3. การบังคับใช้สไตล์เดียวกันบนตารางคอลัมน์ ฯลฯจะช่วยให้สามารถอ่านได้มากเช่นกัน เมื่อฐานข้อมูลเดิมมีตารางPRODUCT, users, USERS_ObsoleteDONT_USE, PR_SHIPMENTSและHRhbYd_UUบางคนจะทำอะไรผิดพลาดมาก

  4. การบังคับใช้สไตล์เดียวกันกับคิวรีมีความสำคัญเช่นกัน ตัวอย่างเช่นหากคุณกำลังเขียนคิวรีสำหรับ Microsoft SQL Server และคุณตัดสินใจที่จะใช้[TableName]แทนTableNameให้ทำตาม หากคุณไปที่บรรทัดใหม่หลังจาก a selectอย่าทำเพียงครึ่งเดียวของแบบสอบถาม แต่ทั้งหมดนั้น

  5. อย่าใช้*เว้นแต่จะมีเหตุผลอันสมควรที่จะทำ (เช่นif exists(select * from [TableName] where ...)ใน Microsoft SQL Server) ไม่เพียง แต่*ส่งผลกระทบด้านลบต่อประสิทธิภาพในฐานข้อมูลบางส่วน (ถ้าไม่ใช่ส่วนใหญ่) แต่ยังไม่เป็นประโยชน์สำหรับนักพัฒนาที่ใช้แบบสอบถามของคุณ ในทำนองเดียวกันผู้พัฒนาจะต้องเข้าถึงค่าตามชื่อโดยไม่ต้องเรียงตามดัชนี

  6. สุดท้ายสำหรับเลือกมีอะไรที่ไม่ถูกต้องในการให้มุมมอง สำหรับขั้นตอนอื่นอาจใช้ขั้นตอนการจัดเก็บขึ้นอยู่กับโครงการและผู้ใช้ที่คุณทำงานด้วย


¹บางคนเกลียดกระบวนการที่เก็บไว้ คนอื่นไม่ชอบพวกเขาด้วยเหตุผลหลายประการ (ถูกต้องสมบูรณ์แบบ, อย่างน้อยก็เพื่อพวกเขา) เหตุผล

²เพื่อนร่วมงานนักเรียนคนอื่นครูของคุณ ฯลฯ


9

ภาพเล็กน้อยในที่มืดที่นี่ แต่ถ้าคุณเขียนมุมมองชั่วคราวจำนวนมากบางทีคุณอาจไม่ได้รู้ว่าสถานที่ส่วนใหญ่คุณสามารถวางตารางในคำสั่ง SQL ตารางนั้นสามารถแทนที่ด้วยแบบสอบถามได้

ดังนั้นแทนที่จะเข้าร่วมตาราง A กับมุมมองชั่วคราว B คุณสามารถเข้าร่วมตาราง A กับแบบสอบถามที่คุณใช้เป็นมุมมองชั่วคราว B ตัวอย่างเช่น

    SELECT A.Col1, A.Col2, B.Col1,B.Col2
      FROM (SELECT RealTableZ.Col1, RealTableY.Col2, RealTableY.ID as ID
              FROM RealTableZ 
   LEFT OUTER JOIN RealTableY
                ON RealTableZ.ForeignKeyY=RealTableY.ID
             WHERE RealTableY.Col11>14
            ) As B
        INNER JOIN A
                ON A.ForeignKeyY=B.ID

ตัวอย่างนี้ค่อนข้างไม่มีจุดหมาย แต่ควรอธิบายไวยากรณ์

สำหรับมุมมองที่ไม่ได้ "พิเศษ" (จัดทำดัชนีแบ่งพาร์ติชัน) สิ่งนี้ควรส่งผลให้เกิดแผนแบบสอบถามแบบเดียวกับที่คุณใช้มุมมอง

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

ฉันขอโทษถ้านี่คือหมวกเก่าแก่คุณแล้ว


3
ฉันค่อนข้างเชี่ยวชาญเกี่ยวกับ SQL และฉันเกลียดการเยื้องนี้: มันอาจดูดี แต่มันไร้ประโยชน์อย่างสมบูรณ์ "ในความคิดของฉัน" เหตุผลสองข้อ: ฉันไม่สามารถเข้าใจได้อย่างชัดเจนว่าการเข้าร่วมด้านนอกด้านซ้ายนั้นเป็นส่วนหนึ่งของแบบสอบถามหลักหรือส่วนหนึ่งของแบบสอบถามย่อยมันต้องใช้ตัวตกแต่งโค้ดและทุกครั้งที่คุณต้องการเพิ่มสองสามบรรทัดคุณจำเป็นต้องตกแต่งข้อความใหม่ทั้งหมด . วางแผนการเยื้องที่ต้องการเพียงแค่ TABS นั้นมีความยืดหยุ่นมากกว่า ฉันไม่ได้ลงคะแนนให้กับคำตอบของคุณ แต่ฉันไม่สนับสนุนให้ใครใช้สไตล์นี้จริง ๆ ... โดยเฉพาะอย่างยิ่งเมื่อพวกเขาต้องการความช่วยเหลือ
Alessandro Rossi

7

แทนที่จะมองเห็นวิวชั่วคราวใช้ประโยคด้วย สิ่งนี้ทำให้ง่ายต่อการแยกเคียวรีขนาดใหญ่ออกเป็นส่วนย่อย ๆ ที่อ่านง่ายขึ้น


1
หากคุณใช้ cte โปรดทราบว่าแบบสอบถามจะยังคงอยู่จนกว่าจะมีการเรียกใช้แบบสอบถามถัดไปดังนั้นในบางกรณีที่คุณใช้ cte ในหลาย ๆ แบบสอบถามอาจเป็นการดีกว่าสำหรับประสิทธิภาพในการใช้ตาราง temp
ราเชล

3
  1. ทำความคุ้นเคยกับทฤษฎีเซตหากคุณยังไม่คุ้นเคย SQL ตั้งอยู่ในทฤษฎีเซตและการทำความเข้าใจเพิ่มเติมเกี่ยวกับเซตจะช่วยให้คุณคุ้นเคยกับการทำงานของ SQL มากขึ้น
  2. ฝึกฝน SQl ให้มากขึ้นถ้าคุณแค่เรียนรู้ SQL มันต้องใช้เวลาในการทำความเข้าใจวิธีทำทุกอย่างสักครู่ก่อนที่คุณจะเข้าใจพวกเขาจริง ๆ การเข้าร่วมเป็นตัวอย่างที่ดียิ่งถ้าคุณใช้พวกเขามากเท่าไหร่
  3. ตรวจสอบให้แน่ใจว่าตารางที่คุณสอบถามได้รับการออกแบบอย่างเหมาะสม
  4. อย่ากลัวที่จะใช้มุมมองกับแบบสอบถามแบบใช้เลือกข้อมูลโดยเฉพาะอย่างยิ่งถ้าคุณมีชุดทั่วไปที่ต้องปรับปรุงหลายวิธี

1

เช่นเดียวกับสิ่งอื่นคุณต้องการแบ่งปัญหาออกเป็นส่วนที่จัดการได้

นั่นคือวิธีที่คุณแก้ปัญหาที่ซับซ้อนโดยวิธีการ

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

คำสั่ง SQL เมื่อมันมาถึงระดับความซับซ้อนโดยพื้นฐานแล้วเป็นโปรแกรมเล็ก ๆ ในตัวมันเอง มันสร้างความแตกต่างอย่างมากในการทำความเข้าใจวิธีการรวมข้อมูลเลือกกรองและเอาท์พุท

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