Bagaimana cara membuat kueri SQL kompleks lebih mudah untuk ditulis? [Tutup]

42

Saya merasa sangat sulit untuk menulis query SQL kompleks yang melibatkan gabungan banyak (setidaknya 3-4) tabel dan melibatkan beberapa kondisi bersarang. Pertanyaan yang saya minta untuk dituliskan dengan mudah dijelaskan oleh beberapa kalimat, tetapi dapat membutuhkan sejumlah kode untuk menyelesaikannya. Saya menemukan diri saya sering menggunakan tampilan sementara untuk menulis pertanyaan ini, yang tampak seperti sedikit penopang. Kiat apa yang dapat Anda berikan yang dapat saya gunakan untuk membuat kueri kompleks ini lebih mudah? Lebih khusus lagi, bagaimana cara memecah pertanyaan ini menjadi langkah-langkah yang perlu saya gunakan untuk benar-benar menulis kode SQL?

Perhatikan bahwa saya SQL yang diminta untuk saya tulis adalah bagian dari pekerjaan rumah untuk kursus basis data, jadi saya tidak ingin perangkat lunak yang akan melakukan pekerjaan untuk saya. Saya ingin benar-benar memahami kode yang saya tulis.

Lebih detail teknis:

  • Basis data di-host pada server PostgreSQL yang berjalan di mesin lokal.
  • Basis datanya sangat kecil: tidak ada lebih dari tujuh tabel dan tabel terbesar memiliki kurang dari 50 baris.
  • Kueri SQL diteruskan tidak berubah ke server, melalui Pangkalan LibreOffice.
bwDraco
sumber
Tampilan sementara sebenarnya cukup berguna karena Anda dapat melakukan hal-hal seperti tabel (seperti indeks kompleks eksplisit) yang sangat sulit untuk mengisyaratkan ke parser SQL.
Secara pribadi, saya merasa lebih mudah untuk menyontek dengan menggunakan GUI (seperti LibreOffice Base "Buat Query di Design View" atau Office Access "Create"> "Query Design") dan kemudian lihat SQL yang dihasilkannya. Kadang-kadang perlu untuk memodifikasi SQL yang diberikan oleh desainer GUI, tetapi itu memberikan titik awal yang baik
kurdtpage

Jawaban:

49

Saya mendasarkan sebagian besar ini pada hanya mencoba untuk mendapatkan jawaban yang "benar", sehingga Anda mungkin menemukan ada beberapa masalah kinerja. Tidak ada gunanya mempercepat permintaan yang salah.

Memahami hubungan tabel - Kebanyakan akan menjadi satu ke banyak. Ketahui tabel "banyak". Identifikasi bidang yang diperlukan untuk bergabung Anda.

Pikirkan tentang skenario bergabung LEFT - Pilih semua karyawan dan gaji mereka dari bulan lalu. Bagaimana jika mereka tidak menerima gaji bulan lalu?

Ketahui set hasil: 1) Dalam spreadsheet, masukkan secara manual setidaknya satu catatan yang benar untuk kueri Anda. 2) Tulis kueri dalam bentuk yang cukup sederhana untuk mengidentifikasi berapa banyak catatan yang harus dikembalikan. Gunakan keduanya untuk menguji kueri Anda untuk memastikan bergabung dengan tabel baru tidak mengubah hasil.

Pisahkan permintaan Anda menjadi beberapa bagian yang dapat dikelola - Anda tidak harus menulis semuanya sekaligus. Query yang kompleks terkadang hanya bisa menjadi kumpulan queries sederhana.

Waspadai tingkat agregasi campuran : Jika Anda harus memasukkan nilai bulanan, triwulanan, dan tahun-ke-tanggal dalam hasil yang sama, Anda harus menghitungnya secara terpisah dalam kueri yang dikelompokkan pada nilai yang berbeda.

Ketahui kapan harus UNION Terkadang lebih mudah untuk memecah subkelompok menjadi pernyataan pilihan mereka sendiri. Jika Anda memiliki tabel yang dicampur dengan manajer dan karyawan lain, dan pada setiap kolom Anda harus melakukan pernyataan Kasus berdasarkan keanggotaan di salah satu dari kelompok ini, mungkin lebih mudah untuk menulis kueri Manajer dan menyatukan ke kueri Karyawan. Masing-masing akan mengandung logikanya sendiri. Harus menyertakan item dari tabel yang berbeda di baris yang berbeda adalah penggunaan yang jelas.

Rumus Kompleks / Bertumpuk - Cobalah membuat indentasi secara konsisten dan jangan takut untuk menggunakan banyak baris. "KASUS KAPAN KASUS KASUS KAPAN" akan membuat Anda gila. Luangkan waktu untuk memikirkan semua ini. Simpan kalori kompleks untuk yang terakhir. Dapatkan catatan yang benar dipilih terlebih dahulu. Lalu, Anda menyerang rumus rumit yang mengetahui Anda bekerja dengan nilai yang benar. Melihat nilai yang digunakan dalam rumus akan membantu Anda melihat area di mana Anda harus memperhitungkan nilai NULL dan di mana menangani pembagian dengan kesalahan nol.

Tes sesering mungkin saat Anda menambahkan tabel baru untuk memastikan Anda masih mendapatkan hasil yang diinginkan dan mengetahui yang bergabung atau klausa adalah penyebabnya.

JeffO
sumber
1
Barang yang sangat bagus. Saya ingin menekankan kembali poin Jeff pada mencari LEFT bergabung dan memecah pertanyaan kompleks menjadi yang lebih kecil, lebih mudah dikelola dan kemudian menggabungkannya. Saya menulis pertanyaan besar pada basis data besar hampir setiap hari dan dua hal itu khususnya muncul setiap saat. Selalu jalankan kueri dan sub kueri Anda sesegera mungkin, untuk memastikan Anda mendapatkan data yang Anda harapkan untuk dilihat di setiap langkah.
CodexArcanum
@ CodexArcanum - dan ketika Anda menjalankan kueri pada data besar, tidak ada salahnya menggunakan TOP;)
JeffO
Saya menyetujui setiap pernyataan saran Anda
Alessandro Rossi
28
  1. Lekukan akan menjadi hal pertama yang harus dilakukan, jika Anda belum melakukannya. Tidak hanya itu berguna bahkan dengan kueri sederhana, tetapi sangat penting ketika datang untuk bergabung dan meminta sedikit lebih kompleks daripada a select top 1 [ColumnName] from [TableName].

  2. Setelah menjorok dengan benar, tidak ada yang melarang untuk menambahkan komentar di dalam kueri itu sendiri, jika perlu. Jangan terlalu sering menggunakannya: jika kodenya cukup eksplisit, menambahkan komentar hanya akan merusak kejelasan kode. Tetapi mereka tetap diterima untuk bagian-bagian yang kurang eksplisit dari permintaan.

    Perhatikan bahwa kueri yang lebih panjang (termasuk kueri dengan komentar) akan berarti penggunaan bandwidth yang lebih besar antara server aplikasi Anda dan server database Anda. Perhatikan juga bahwa kecuali Anda bekerja pada produk skala Google dengan jumlah permintaan yang sangat besar per detik, membutuhkan kinerja yang luar biasa dan penggunaan sumber daya, ukuran yang ditambahkan oleh komentar tidak dapat mengubah apa pun untuk Anda dalam hal kinerja.

  3. Menegakkan gaya yang sama di atas tabel, kolom, dll. Juga membantu keterbacaan banyak. Ketika database warisan memiliki meja PRODUCT, users, USERS_ObsoleteDONT_USE, PR_SHIPMENTSdan HRhbYd_UU, seseorang melakukan sesuatu yang sangat salah.

  4. Menegakkan gaya yang sama atas permintaan juga penting. Misalnya jika Anda menulis query untuk Microsoft SQL Server dan Anda memutuskan untuk menggunakan [TableName]bukan TableName, tongkat dengan itu. Jika Anda pergi ke baris baru setelah a select, jangan lakukan hanya dalam setengah dari pertanyaan Anda, tetapi semuanya.

  5. Jangan gunakan* , kecuali ada alasan kuat untuk melakukannya (seperti di if exists(select * from [TableName] where ...)dalam Microsoft SQL Server). Tidak hanya *memiliki dampak kinerja negatif di beberapa (jika tidak sebagian besar) database, tetapi juga tidak membantu bagi pengembang yang menggunakan kueri Anda. Dengan cara yang sama, pengembang harus mengakses nilai berdasarkan nama, tidak pernah dengan indeks.

  6. Akhirnya, untuk pilihan, tidak ada yang salah dalam memberikan tampilan . Untuk hal lain, prosedur tersimpan dapat juga digunakan tergantung pada proyek dan orang-orang yang bekerja dengan Anda.


¹ Beberapa orang membenci prosedur tersimpan. Orang lain tidak suka mereka karena beberapa alasan (valid sempurna, setidaknya untuk mereka).

² Kolega Anda, siswa lain, guru Anda, dll.

Arseni Mourzenko
sumber
9

Sedikit tembakan dalam kegelapan di sini, tetapi jika Anda menulis banyak pandangan sementara mungkin Anda belum menyadari bahwa sebagian besar tempat Anda bisa meletakkan tabel dalam pernyataan SQL, tabel itu dapat diganti dengan kueri.

Jadi, daripada bergabung dengan tabel A ke tampilan sementara B, Anda dapat bergabung dengan tabel A ke kueri yang telah Anda gunakan sebagai tampilan sementara B. Misalnya:

    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

Contoh ini agak tidak berguna, tetapi harus menjelaskan sintaksisnya.

Untuk tampilan yang bukan "spesial" (diindeks, dipartisi) ini akan menghasilkan rencana permintaan yang sama seperti jika Anda menggunakan tampilan.

Sejauh membuatnya lebih mudah untuk menulis, Anda dapat memverifikasi setiap bagian untuk memastikan Anda mendapatkan apa yang Anda harapkan sebelum menuliskan seluruh permintaan.

Saya minta maaf jika ini topi lama untuk Anda.

psr
sumber
3
Saya cukup ahli tentang SQL dan saya sangat membenci lekukan ini: mungkin terlihat bagus tetapi sama sekali tidak berguna "menurut pendapat saya". Dua alasan: Saya tidak dapat memahami dengan jelas apakah gabungan luar kiri itu adalah bagian dari kueri utama atau bagian dari subquery, itu memerlukan kode ahli kecantikan dan setiap kali Anda ingin menambahkan beberapa baris, Anda perlu mempercantik kembali semua teks . Rencanakan lekukan yang hanya membutuhkan TABS jauh lebih fleksibel. Saya tidak memberi suara rendah pada jawaban Anda, tetapi saya benar-benar mencegah siapa pun yang menggunakan gaya ini ... terutama ketika mereka membutuhkan bantuan saya.
Alessandro Rossi
7

Alih-alih pandangan sementara, menggunakan klausa WITH . Ini membuatnya lebih mudah untuk memecah pertanyaan besar menjadi bagian-bagian kecil yang lebih mudah dibaca.

pengguna281377
sumber
1
Jika Anda menggunakan cte, ketahuilah bahwa kueri hanya bertahan hingga kueri berikutnya dijalankan, jadi dalam beberapa kasus saat Anda menggunakan cte dalam beberapa kueri, kinerja mungkin lebih baik menggunakan tabel temp.
Rachel
3
  1. Menjadi lebih akrab dengan teori himpunan jika Anda belum melakukannya. SQL didasarkan pada teori himpunan dan memahami lebih banyak tentang himpunan akan membantu Anda menjadi lebih terbiasa dengan cara kerja SQL.
  2. Berlatih lebih banyak SQl, jika Anda baru belajar SQL akan butuh waktu untuk memahami bagaimana melakukan semuanya, kadang-kadang hanya butuh waktu sebelum Anda benar-benar mengerti mereka, Bergabung adalah contoh yang bagus semakin Anda menggunakannya semakin baik Anda akan mendapatkannya.
  3. Pastikan tabel yang Anda tanyakan dirancang dengan benar
  4. Jangan takut menggunakan tampilan pada kueri tertentu, terutama jika Anda memiliki set umum yang perlu disempurnakan dengan berbagai cara
Ryathal
sumber
1

Seperti yang lainnya, Anda ingin memecah masalah menjadi beberapa bagian yang dapat dikelola.

Ngomong-ngomong, itu memang cara Anda memecahkan masalah yang rumit.

Jadi: Anda ingin memeriksa subquery untuk melihat apakah itu benar-benar mengembalikan apa yang Anda inginkan sebelum menjalankan kueri luar di atasnya. Anda ingin mencoba gabungan minimal dari setiap tabel yang Anda ikuti sehingga Anda dapat melihat bahwa Anda benar-benar memikirkannya dengan baik. Hal-hal seperti itu. Berharap untuk mengetik semuanya dan keluar persis seperti yang Anda inginkan dalam satu pukulan saja tidak realistis.

Pernyataan SQL, setelah mencapai tingkat kerumitan tertentu, pada dasarnya adalah sebuah program kecil. Itu membuat perbedaan besar untuk benar-benar memahami bagaimana data digabungkan, dipilih, difilter, dan keluaran.

Dan Ray
sumber