Package yang digunakan
library(DBI)
library(RSQLite)
library(tidyverse)
library(DT)
Database
Database yang digunakan adalah database chinook
yang terdiri dari 13 tabel seperti dapat terlihat pada diagram berikut
Koneksi ke database
Berikut adalah syntax untuk menyambungkan database chinook dengan R
<-DBI::dbConnect(RSQLite::SQLite(), "C:/sqlite/db/Chinook.db") Chinook
Melihat tabel dalam Database
Untuk melihat tabel-tabel yang ada dalam database, bisa menggunakan perintah berikut
dbListTables(Chinook)
## [1] "albums" "artists" "customers" "employees"
## [5] "genres" "invoice_items" "invoices" "media_types"
## [9] "playlist_track" "playlists" "sqlite_sequence" "sqlite_stat1"
## [13] "tracks"
Akses database
Untuk mengakses data dari database, dapat dilakukan dengan 2 cara yaitu :
Mengambil satu tabel secara keseluruhan
Menggunakan fungsi dbReadTable
pada package DBI, dengan memasukkan nama koneksi dan nama tabel yang akan diambil. Misal akan diambil tabel genres
<- dbReadTable(Chinook, name="genres") tab_genre
Menggunakan query
Terdapat 2 cara untuk melakukan query SQL dalam R. Misal akan ditampilkan judul lagu dari album dengan albumId=1. Bisa dilakukan dengan 2 cara sebagai berikut :
Cara 1
Menggunakan fungsi dbgetquery()
pada package DBI dengan memasukkan nama koneksi dan statement query.
<- dbGetQuery(Chinook, sql
query "SELECT Name
( FROM Tracks
WHERE AlbumId=1"))
Cara 2
Dengan menambahkan argument pada code chunk, yaitu connection, engine, dan output.var
Berikut adalah hasil yang ditampilkan
Advanced SQL Query
Selanjutnya akan dilakukan beberapa operasi SQL Query pada database chinook sebagai berikut
1. Operations on NULL values
NULL digunakan untuk mewakili nilai yang hilang dan bisa diinterpretasikan ke dalam 3 kondisi yaitu :
1. Tidak diketahui (unknown value)
2. Ada, namun tidak ingin diketahui (unavailable)
3. Tidak memiliki (Not applicable attribute)
Seringkali tidak mungkin untuk menentukan makna dari NULL, sehingga SQL tidak membedakan arti dari NULL
SQL memungkinkan query untuk mengecek adanya nilai NULL dengan IS NULL atau IS NOT NULL. SQL tidak menggunakan “=” atau “<>” untuk membandingkan nilai atribut dengan nilai NULL, karena SQL menganggap setiap nilai NULL berbeda dengan nilai NULL lainnya. Hal ini menyebabkan apabila terdapat kondisi join, tuple dengan nilai NULL tidak akan dimasukkan ke dalam hasil (kecuali outer join).
Query 1 : Menampilkan Nama Depan, Nama Belakang, Nama Perusahaan, dan Kota dari Customers dengan kondisi Nama Perusahaan bernilai NULL
SELECT FirstName, LastName, Company, City
FROM customers
WHERE Company IS NULL
2. Nested Queries
Beberapa query mengharuskan nilai yang ada dalam database diambil untuk kemudian dimasukkan dalam kondisi perbandingan. Nested query merupakan query SELECT-FROM-WHERE yang berada di dalam WHERE query sebelumnya (outer query). Operator perbandingan yang digunakan adalah IN
Query 2 : Menampilkan id dan judul-judul lagu yang dibeli di negara Denmark
SELECT TrackId, Name
FROM tracks
WHERE TrackId IN (SELECT TrackId
FROM invoice_items
WHERE InvoiceId IN (SELECT InvoiceId
FROM invoices
WHERE BillingCountry='Denmark'))
ORDER BY (TrackId)
Selain itu juga dapat digunakan operator lain selain operator IN
dalam nested query, seperti =, >, >=, <, <=, <>
Query 2a : Menampilkan negara-negara dan total pembelian dimana customers melakukan pembelian lebih dari invoiceId ke 5 yang memiliki total pembelian 13.86
SELECT BillingCountry, Total
FROM invoices
WHERE Total > (SELECT Total
FROM invoices
WHERE InvoiceId = 5)
4. EXISTS and NOT EXISTS Functions
EXISTS adalah suatu fungsi Boolean yang mengembalikan nilai TRUE atau FALSE. EXISTS digunakan untuk mengecek apakah hasil query yang dihasilkan oleh nested query kosong atau tidak, sehingga EXIST dan NOT EXISTS biasanya digunakan bersamaan dengan nested query. Sebagai contoh akan ditampilkan kembali query 2 dengan opsi lain menggunakan EXISTS
Query 4a : Menampilkan id dan judul-judul lagu yang dibeli di negara Denmark
SELECT TrackId, Name
FROM tracks as T
WHERE EXISTS (SELECT *
FROM invoice_items AS II, invoices AS I
WHERE T.TrackId = II.TrackId AND I.InvoiceId = II.InvoiceId
AND I.BillingCountry='Denmark')
ORDER BY (TrackId)
Contoh penggunaan NOT EXIST
Query 4b : Menampilkan nama depan dan nama belakang pegawai yang tidak menangani customers
SELECT FirstName, LastName
FROM employees as E
WHERE NOT EXISTS (SELECT *
FROM customers as C
WHERE E.EmployeeId = C.SupportRepId)
5. EXPLICIT SETS
Opsi lain untuk menggantikan nested value adalah dengan menerapkan suatu set nilai eksplisit di dalam WHERE. Sebagai contoh dan perbandingan, akan dilakukan lagi Query 2 yang sebelumnya menggunakan nested value digantikan dengan explisit set
Query 5 : Menampilkan id dan judul-judul lagu yang dibeli di negara Denmark
SELECT T.TrackId, T.Name
FROM tracks AS T, invoice_items AS II, invoices AS I
WHERE T.TrackId = II.TrackId AND I.InvoiceId = II.InvoiceId
AND BillingCountry IN('Denmark')
ORDER BY (T.TrackId)
6. RENAMING Attribute
Dalam SQL, dimungkinkan untuk mengganti nama attribute hasil query dengan menggunakan perintah AS
.
Akan dicontohkan dengan menggunakan query 4b dimana attribute FirstName akan diubah menjadi Nama_Depan dan LastName akan diubah menjadi Nama_Belakang
Query 6 : Menampilkan nama depan dan nama belakang pegawai yang tidak menangani customers
SELECT FirstName AS Nama_Depan, LastName AS Nama_Belakang
FROM employees as E
WHERE NOT EXISTS (SELECT *
FROM customers as C
WHERE E.EmployeeId = C.SupportRepId)
7. Joined Relations
Joined relations dimasukkan ke dalam klausa FROM
. Dapat menggunakan JOIN, CROSS JOIN, atau NATURAL JOIN.
Query 7 : Menampilkan album yang penyanyinya adalah Aerosmith
SELECT Title
FROM albums AS AL, artists AS AR
WHERE Name='Aerosmith' AND AL.ArtistId=AR.ArtistId
atau dapat juga dengan menggunakan query seperti di bawah ini
SELECT Title
FROM (albums as AL JOIN artists AS AR ON AR.ArtistId=AL.ArtistId)
WHERE Name='Aerosmith'
SELECT Title
FROM (albums NATURAL JOIN artists)
WHERE Name='Aerosmith'
Dapat pula dilakukan nest join, dimana salah satu tabel yang di join merupakan tabel hasil join. Hal ini memungkinkan 3 atau lebih tabel menjadi satu tabel gabungan yang disebut multiway join
.
Contoh lainnya adalah dengan melakukan join terlebih dahulu antara tabel album dengan tabel artist, kemudian hasil join tersebut dijoin lagi dengan tabel tracks
Query 7c : Menampilkan judul lagu, composer, dan harga satuan dari band Queen.
SELECT T.Name, T.Composer, T.UnitPrice
FROM ((albums AS AL JOIN artists AS AR ON AR.ArtistId=AL.ArtistId) JOIN tracks AS T ON T.AlbumId=AL.AlbumId)
WHERE AR.Name='Queen'
8. Aggregate Function
Aggregate function adalah fungsi-fungsi yang dapat digunakan saat query yang mencakup operasi COUNT, SUM, MAX, MIN, dan AVG
Query 8 : Menampilkan jumlah pembelian, Pembelian tertinggi, Pembelian terendah, dan rata-rata pembelian yang dilakukan oleh semua customers
SELECT SUM(Total) AS Jml_Pembelian, MAX(Total) AS Pembelian_Tertinggi,
MIN(Total) AS Pembelian_Terendah, AVG(Total) AS Rata_Pembelian
FROM invoices
Dapat juga ditambahkan suatu kondisi tertentu sebagai berikut
Query 8a : Menampilkan jumlah pembelian, Pembelian tertinggi, Pembelian terendah, dan rata-rata pembelian yang dilakukan oleh customers di negara USA
SELECT SUM(Total) AS Jml_Pembelian, MAX(Total) AS Pembelian_Tertinggi,
MIN(Total) AS Pembelian_Terendah, AVG(Total) AS Rata_Pembelian
FROM invoices
WHERE BillingCountry='USA'
Selain itu dapat pula digabungkan dengan query JOIN sebagai berikut
Query 8b : Menampilkan jumlah pembelian, Pembelian tertinggi, Pembelian terendah, dan rata-rata pembelian yang dilakukan oleh customers bernama depan Dominique
SELECT SUM(Total) AS Jml_Pembelian, MAX(Total) AS Pembelian_Tertinggi,
MIN(Total) AS Pembelian_Terendah, AVG(Total) AS Rata_Pembelian
FROM (invoices AS I JOIN customers AS C ON I.CustomerId=C.CustomerId)
WHERE C.FirstName='Dominique'
Contoh penggunaan fungsi agregate COUNT
Query 8c : Menghitung banyaknya lagu
SELECT COUNT(*) AS JumlahLagu
FROM tracks
Query 8d : Menghitung banyaknya lagu yang memiliki genre metal
SELECT COUNT(*) AS JumlahLaguMetal
FROM tracks AS T, genres AS G
WHERE T.GenreId=G.GenreId AND G.Name='Metal'
Queri 8e : Menampilkan nama perusahaan dan negaranya yang melakukan transaksi lebih dari 5 kali (penggabungan dengan nested query)
SELECT C.Company, C.Country
FROM customers AS C
WHERE (SELECT COUNT(*)
FROM invoices AS I
WHERE I.CustomerId=C.CustomerId)>5
9. Grouping
Jika kita ingin menerapkan fungsi agregat untuk tiap subkelompok tupples, dapat digunakan perintah GROUP BY. Perintah GROUP BY digunakan untuk untuk menentukan atribute mana yang dijadikan dasar pengelompokkan.
Query 9a : Untuk setiap genre, akan ditampilkan banyaknya lagu dan rata-rata harganya
SELECT GenreId, COUNT(*) AS JumlahLagu, AVG(UnitPrice) AS RataRataHarga
FROM tracks
GROUP BY GenreId
Query 9b : Untuk setiap Tipe Media, akan ditampilkan MediaTypeId, Nama Media, dan jumlah lagu yang menggunakan media tersebut (penggabungan dengan operasi join)
SELECT M.MediaTypeId, M.Name AS Media, COUNT(*) AS JumlahLagu
FROM media_types AS M, tracks AS T
WHERE M.MediaTypeId=T.MediaTypeId
GROUP BY M.MediaTypeId, M.Name
10. HAVING clause
Jika kita ingin mengambil nilai dari suatu fungsi agregat hanya untuk grup yang memenuhi kondisi tertentu, maka dapat digunakan perintah HAVING
. HAVING digunakan untuk menentukan kondisi seleksi pada grup (bukan tupples secara individu)
Query 10a : Pada Query 9b sebelumnya, akan diseleksi lagi hanya menampilkan jumlah lagu berdasarkan medianya yang memiliki jumlah lagu lebih dari 100 lagu
SELECT M.MediaTypeId, M.Name AS Media, COUNT(*) AS JumlahLagu
FROM media_types AS M, tracks AS T
WHERE M.MediaTypeId=T.MediaTypeId
GROUP BY M.MediaTypeId, M.Name
HAVING COUNT(*)>100
Query 10b : Untuk setiap tipe media, akan ditampilkan mediatypeId, nama media, dan jumlah lagu yang menggunakan media tersebut, hanya untuk lagu dengan genre Alternative (menambahkan tabel baru yaitu genres)
SELECT M.MediaTypeId, M.Name AS Media, COUNT(*) AS JumlahLagu
FROM media_types AS M, tracks AS T, genres AS G
WHERE M.MediaTypeId=T.MediaTypeId AND G.GenreId=T.GenreId
AND G.Name='Alternative'
GROUP BY M.MediaTypeId, M.Name