Fungsi OVER dan PARTITION BY keduanya adalah fungsi yang digunakan untuk membagi hasil yang ditetapkan menurut kriteria yang ditentukan.
Artikel ini menjelaskan bagaimana kedua fungsi ini dapat digunakan bersama untuk mengambil data yang dipartisi dengan cara yang sangat spesifik.
Menyiapkan Beberapa Contoh Data
Untuk mengeksekusi kueri sampel kami, pertama-tama mari buat database bernama "studentdb".
Jalankan perintah berikut di jendela kueri Anda:
BUAT DATABASE schooldb;
Selanjutnya, kita perlu membuat tabel “student” di dalam database “studentdb”. Tabel siswa akan memiliki lima kolom:id, nama, usia, jenis kelamin, dan total_score.
Seperti biasa, pastikan Anda didukung dengan baik sebelum bereksperimen dengan kode baru. Lihat artikel ini tentang mencadangkan database SQL Server jika Anda tidak yakin.
Jalankan kueri berikut untuk membuat tabel siswa.
GUNAKAN schooldbCREATE TABLE siswa( id INT PRIMARY KEY IDENTITY, nama VARCHAR(50) NOT NULL, jenis kelamin VARCHAR(50) NOT NULL, usia INT NOT NULL, total_score INT NOT NULL, )
Terakhir, kita perlu memasukkan beberapa data dummy untuk kita kerjakan ke dalam database.
GUNAKAN schooldbINSERT INTO student VALUES ('Jolly', 'Female', 20, 500), ('Jon', 'Male', 22, 545), ('Sara', 'Female', 25, 600), ('Laura', 'Wanita', 18, 400), ('Alan', 'Pria', 20, 500), ('Kate', 'Wanita', 22, 500), ('Joseph', 'Pria' , 18, 643), ('Tikus', 'Pria', 23, 543), ('Bijaksana', 'Pria', 21, 499), ('Elis', 'Wanita', 27, 400);Saat ini kami siap untuk mengatasi masalah dan melihat siapa yang dapat kami gunakan Over dan Partition By untuk menyelesaikannya.
Masalah
Kami memiliki 10 record di tabel siswa dan kami ingin menampilkan nama, id, dan jenis kelamin untuk semua siswa, dan selain itu kami juga ingin menampilkan jumlah siswa yang dimiliki setiap jenis kelamin, usia rata-rata siswa siswa dari setiap jenis kelamin dan jumlah nilai dalam kolom total_score untuk setiap jenis kelamin.
Kumpulan hasil yang kita cari adalah seperti di bawah ini:
Seperti yang Anda lihat, tiga kolom pertama (ditampilkan dalam warna hitam) berisi nilai individual untuk setiap catatan, sedangkan tiga kolom terakhir (ditampilkan dalam warna merah) berisi nilai gabungan yang dikelompokkan menurut kolom jenis kelamin. Misalnya, di kolom Average_Age, lima baris pertama menampilkan usia rata-rata dan skor total semua catatan dengan jenis kelamin Perempuan.
Kumpulan hasil kami berisi hasil gabungan yang digabungkan dengan kolom non-agregat.
Untuk mengambil hasil agregat, dikelompokkan berdasarkan kolom tertentu, kita dapat menggunakan klausa GROUP BY seperti biasa.
GUNAKAN schooldbSELECT gender, count(gender) AS Total_Students, AVG(age) as Average_Age, SUM(total_score) as Total_ScoreFROM studentGROUP BY genderMari kita lihat bagaimana kita dapat mengambil Total_Students, Average_Age, dan Total_Score siswa yang dikelompokkan berdasarkan gender.
Anda akan melihat hasil berikut:
Sekarang mari kita perluas ini dan menambahkan 'id' dan 'name' (kolom non-agregat dalam pernyataan SELECT) dan lihat apakah kita bisa mendapatkan hasil yang kita inginkan.
GUNAKAN schooldbSELECT id, name, gender, count(gender) AS total_students, AVG(age) as Average_Age, SUM(total_score) as Total_ScoreFROM studentGROUP BY genderSaat Anda menjalankan kueri di atas, Anda akan melihat kesalahan:
Kesalahan mengatakan bahwa kolom id tabel siswa tidak valid dalam pernyataan SELECT karena kami menggunakan klausa GROUP BY dalam kueri.
Ini berarti bahwa kita harus menerapkan fungsi agregat pada kolom id atau kita harus menggunakannya dalam klausa GROUP BY. Singkatnya, skema ini tidak menyelesaikan masalah kita.
Solusi Menggunakan Pernyataan JOIN
Salah satu solusi untuk ini adalah dengan menggunakan pernyataan JOIN untuk menggabungkan kolom dengan hasil agregat ke kolom yang berisi hasil non-agregat.
Untuk melakukannya, Anda memerlukan sub-kueri yang mengambil jenis kelamin, Total_Students, Average_Age, dan Total_Score siswa yang dikelompokkan berdasarkan jenis kelamin. Hasil ini kemudian dapat digabungkan dengan hasil yang diperoleh dari sub-kueri dengan pernyataan SELECT luar. Ini akan diterapkan ke kolom jenis kelamin dari subkueri yang berisi hasil gabungan dan kolom jenis kelamin dari tabel siswa. Pernyataan SELECT luar akan menyertakan kolom non-agregat yaitu 'id' dan 'name', seperti di bawah ini.
GUNAKAN schooldbSELECT id, name, Aggregation.gender, Aggregation.Total_students, Aggregation.Average_Age, Aggregation.Total_ScoreFROM studentINNER JOIN(SELECT gender, count(gender) AS Total_students, AVG(age) AS Average_Age, SUM(total_ScoreF AS) studentGROUP BY gender) AS Aggregationon Aggregation.gender =student.genderKueri di atas akan memberi Anda hasil yang diinginkan tetapi bukan solusi optimal. Kami harus menggunakan pernyataan GABUNG dan sub-kueri yang meningkatkan kompleksitas skrip. Ini bukan solusi yang elegan atau efisien.
Pendekatan yang lebih baik adalah menggunakan klausa OVER dan PARTITION BY secara bersamaan.
Solusi Menggunakan OVER dan PARTITION BY
Untuk menggunakan klausa OVER dan PARTITION BY, Anda hanya perlu menentukan kolom yang Anda inginkan untuk mempartisi hasil agregat Anda. Ini paling baik dijelaskan dengan menggunakan contoh.
Mari kita lihat pencapaian hasil kita menggunakan OVER dan PARTITION BY.
GUNAKAN schooldbSELECT id, name, gender,COUNT(gender) OVER (PARTITION BY gender) AS Total_students,AVG(age) OVER (PARTITION BY gender) AS Average_Age,SUM(total_score) OVER (PARTITION BY gender) AS Total_ScoreFROM studentIni adalah hasil yang jauh lebih efisien. Di baris pertama skrip, kolom id, nama, dan jenis kelamin diambil. Kolom ini tidak berisi hasil gabungan.
Selanjutnya untuk kolom yang berisi hasil agregasi cukup kita tentukan fungsi agregasinya, diikuti dengan klausa OVER lalu di dalam kurung kita tentukan klausa PARTITION BY diikuti dengan nama kolom yang kita inginkan hasil kita dipartisi seperti pada gambar di bawah.
Referensi
- Microsoft – Memahami klausa OVER
- Midnight DBA – Pengantar OVER dan PARTITION BY
- StackOverflow – Perbedaan Antara PARTITION BY dan GROUP BY