kurungkurawal.com, menyajikan berbagai kode sumber dalam beberapa bahasa pemrograman. Hasil google analytics menunjukkan adanya visitor dari wilayah di luar Indonesia. Karena hal tersebut, beberapa waktu lalu, saya menggunakan tools dari google, yaitu Google Translate, untuk membantu melayani visitor yang tidak berbahasa Indonesia.
Continue Reading…
Java Swing, Membaca Kode Warna Heksadesimal
Bagi Anda yang pernah bermain dengan grafik digital, misalnya Web Design, pasti pernah melihat kode warna dalam format misalnya #FFFFFF
bukan? Format tersebut adalah representasi warna dalam bilangan Heksadesimal, yang mana terdiri dari 6 digit (di CSS, dapat hanya menggunakan 3 digit) , dengan mencakup 3 Warna Dasar, yaitu Red, Green, dan Blue.
Masing masing warna tersebut direpresentasikan oleh 2 digit bilangan heksadesimal, yang berarti nilai tertinggi dari bilang tersebut adalah FF atau 255, kunjungi tautan berikut untuk proses konversinya.
Dalam post kali ini, Saya ingin memberikan contoh implementasi kode warna Heksadesimal tersebut dalam bahasa pemrograman Java, khususnya dengan menggunakan komponen Swing
. Class yang dapat digunakan adalah java.awt.Color
. Yang mana, class tersebut dapat di-construct dengan parameter integer
, yang mana dapat merupakan representasi nilai bilangan dari huruf heksadesimal.
Sedangkan untuk mengkonversi String
Heksadesimal menjadi integer
, dapat menggunakan fungsi bawaan Integer.parseInt(String, int Radix)
, dimana radix disini adalah nilai basis bilangan, dalam hal heksadesimal ini, adalah 16. Iya, heksadesimal adalah bilangan berbasis 16.
Proses konversi String Heksadesimal menjadi integer, dapat dilakukan, misalnya dengan kode berikut
1 2 3 4 5 6 7 8 9 | Static Color parseColor(String hex){ try { int hexValue = Integer.parseInt(hex, 16); return new Color(hexValue); } catch (Exception e){ e.printStackTrace(); return null; } } |
Dan berikut saya berikan contoh kode untuk diaplikasikan dalam aplikasi Java, tentu saja, kode berikut hanya mendemonstrasikan bagaimana proses konversi dan penggunaan Color
tersebut. Berbagai error handling mungkin harus diterapkan dalam aplikasi sebenarnya.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | package com.kurungkurawal.spo; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; /** * Created by konglie on 3/7/16. */ public class HexColors extends JFrame { public static void main(String[] args){ new HexColors(); } JPanel body, headerPanel, colorPanel; JTextField inputColor; JButton btnProcess; public HexColors(){ setTitle("Contoh Warna dari String Heksadesimal"); setResizable(false); setPreferredSize(new Dimension(640, 480)); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); body = new JPanel(new BorderLayout()); inputColor = new JTextField("DD3333"); btnProcess = new JButton("Proses"); btnProcess.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { processInput(); } }); headerPanel = new JPanel(new BorderLayout()); headerPanel.setBorder(BorderFactory.createEmptyBorder(5,15,5,15)); headerPanel.add(new JLabel("Kode Warna Heksadesimal, 6 Digit"), BorderLayout.WEST); headerPanel.add(inputColor, BorderLayout.CENTER); headerPanel.add(btnProcess, BorderLayout.EAST); body.add(headerPanel, BorderLayout.NORTH); colorPanel = new JPanel(); colorPanel.setOpaque(true); body.add(colorPanel, BorderLayout.CENTER); getContentPane().add(body, BorderLayout.CENTER); pack(); setLocationRelativeTo(null); setVisible(true); processInput(); } void processInput(){ final Color color = parseColor(); if(color == null){ JOptionPane.showMessageDialog(null, "Gagal membaca kode warna"); } else { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { colorPanel.setBackground(color); } }); } } Color parseColor(){ try { String hex = inputColor.getText(); if(hex.startsWith("#")){ hex = hex.replaceAll("^#", ""); } int hexValue = Integer.parseInt(hex, 16); return new Color(hexValue); } catch (Exception e){ e.printStackTrace(); return null; } } } |
Demikian, semoga berguna untuk kita semua.
Javascript Menghapus atau mengganti data di Array dengan splice()
Kadang kita butuh untuk menghapus atau mengganti data ke n di dalam array javascript. Misalnya,
1 | var arr = ['satu', 'dua', 'apel', 'empat', 'lima']; |
Kita akan menghapus element apel
dari array di atas.
1 2 3 4 5 | var arr = ['satu', 'dua', 'apel', 'empat', 'lima']; arr.splice(2,1); // arr sekarang adalah ["satu", "dua", "empat", "lima"] console.log(arr); |
Atau, sebagai salah satu contoh lain fungsi splice()
adalah kita mengganti apel
menjadi tiga
, misalnya
1 2 3 4 5 | var arr = ['satu', 'dua', 'apel', 'empat', 'lima']; arr.splice(2,1, 'tiga'); // arr sekarang adalah ["satu", "dua", "tiga", "empat", "lima"] console.log(arr); |
Lalu apa maksud dari splice(2,1)
, itu berarti bahwa kita akan menghapus mulai dari index ke 2 sebanyak 1 buah. Jangan lupa, bahwa perhitungan index array adalah dimulai dari 0. Sehingga, di contoh di atas, kata apel
berada di index ke 2. Cara lain, bisa juga dengan
1 | arr.splice( arr.indexOf('apel'), 1 ); |
arr.indexOf('apel');
berarti mencari posisi apel
pada array arr
. Tentu saja akan banyak sekali penggunaan fungsi splice()
ini sesuai dengan kebutuhan dan pengembangan pada script yang digunakan. Namun, topik kali ini hanya bertujuan memperkenalkan cara menghapus dan mengganti data di array javascript.
Demikian, semoga berguna untuk kita semua.
Javascript Mengganti kata/karakter dalam String
String di Javascript memiliki method replace()
, yang berfungsi untuk mencari sebuah nilai, yang sesuai dengan String atau Regular Expression
yang telah ditentukan, dan kemudian mengganti hasil pencarian tersebut dengan String yang telah ditentukan pula.
Misalnya,
1 2 3 4 5 | var str = "Selamat datang di Jakarta."; var strBaru = str.replace('Jakarta', 'Bandung'); // strBaru telah menjadi "Selamat datang di Bandung" console.log(strBaru); |
Namun, perlu diingat jika menggunakan sintaks di atas, maka penggantian hanya terjadi 1 kali saja. Misalnya dalam kasus seperti di bawah ini
1 2 3 4 5 | var str = "Selamat datang di Jakarta. Kota Jakarta adalah merupakan kota besar."; var strBaru = str.replace('Jakarta', 'Bandung'); // strBaru telah menjadi "Selamat datang di Bandung. Kota Jakarta adalah merupakan kota besar." console.log(strBaru); |
Perhatikan bahwa, kata “Jakarta” hanya tergantikan 1 kali saja. Untuk menggantikan sebuah kata secara menyeluruh, gunakan Regular Expression
, dan berikan tanda global
atau g
, seperti pada contoh di bawah
1 2 3 4 5 | var str = "Selamat datang di Jakarta. Kota Jakarta adalah merupakan kota besar."; var strBaru = str.replace(/Jakarta/g, 'Bandung'); // strBaru telah menjadi "Selamat datang di Bandung. Kota Bandung adalah merupakan kota besar." console.log(strBaru); |
Sekedar catatan, jika Anda menggunakan console.log(string)
, hasilnya dapat dilihat menggunakan Web Developer Tools di Google Chrome, plugin Firebug di Firefox atau tools lainnya. Atau jika bingung, gunakan saja fungsi alert
Javascript.
Demikian, semoga berguna untuk kita semua.
PHP Menghitung jumlah data di table MySQL
Ada kalanya aplikasi PHP kita butuh untuk mengetahui jumlah data di dalam suatu table database, dalam contoh kali ini, database MySQL. Misalnya, mengetahui jumlah member, mengetahui jumlah transaksi, dan lain sebagainya.
Untuk keperluan tersebut, MySQL menyediakan fungsi count()
untuk mengetahui jumlah data dari sebuah query. Dipahami ya, bahwa jumlah data sebuah query, tidak selalu berarti jumlah data dalam suatu table. Lebih detail mengenai ini akan dibahas lain waktu, semoga ada kesempatan itu.
Kembali ke topik kita, cara kedua adalah, menggunakan fungsi dari driver MySQL di PHP, mysql_num_rows()
.
Dan cara ketiga, adalah cara yang paling tradisional dan, seringnya, tidak efektif, yaitu mengambil seluruh data dari query ke dalam sebuah variable penampung, misalnya Array(), dan kemudian menghitung jumlah isi dari Array tersebut.
Kenapa cara ketiga ini (sering kali) tidak efektif ? Bayangkan jika query yang ingin kita hitung jumlah hasilnya tersebut ternyata memberikan hasil 1 juta record. Berapa banyak memory yang diperlukan untuk menampung data data tersebut ? Jawabannya tentu saja tergantung dari bagaimana struktur data per-record. Yang pasti, besar.
Tentu saja, tergantung kebutuhan Anda, saya sajikan contoh dari 3 cara di atas. Anda ada cara lain? Silakan dishare.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?php mysql_connect('localhost', 'username', 'password'); mysql_select_db('dbname'); $table = "tablename"; // Cara 1 $sql = "SELECT count(*) AS jumlah FROM $table"; $query = mysql_query($sql); $result = mysql_fetch_array($query); echo "Jumlah data dengan fungsi MySQL count(): {$result['jumlah']} <br/>"; // Cara 2 $sql = "SELECT * FROM $table"; $query = mysql_query($sql); $count = mysql_num_rows($query); echo "Jumlah data dengan mysql_num_rows: $count <br/>"; // Cara 3 $sql = "SELECT * FROM $table"; $query = mysql_query($sql); $data = array(); while(($row = mysql_fetch_array($query)) != null){ $data[] = $row; } $count = count($data); echo "Jumlah data dari array PHP: $count"; |
Jangan lupa, seluruh contoh di atas adalah menghitung sebenarnya adalah menghitung jumlah data dari hasil query. Karena querynya adalah mengambil seluruh data dari $table
, maka bisa dibilang contoh di atas adalah menampilkan jumlah data di dalam $table
.
Fungsi-fungsi di atas dapat dikembangkan menjadi lebih kompleks, misalnya menghitung jumlah member yang hanya mendaftar tapi belum aktif, atau menghitung jumlah mahasiswa yang sudah lebih 6 tahun betah di kampus, atau menghitung jumlah transaksi yang belum lunas dan atau-atau lainnya.
Demikian semoga berguna untuk kita semua.
Format Baris Teks untuk dokumen menggunakan Java
Banyak library Java yang memberikan kemudahan untuk menciptakan dokumen dalam format Excel, PDF, dan format modern (dan canggih) lainnya. Namun bagaimana jika yang dibutuhkan hanya untuk membuat dokumen teks sederhana saja, namun membutuhkan pengaturan baris sederhana, misalnya kolom, dan rata kiri-kanan-tengah.
Kasus yang umum terjadi misalnya, ketika membuat dokumen yang akan dicetak dengan menggunakan printer Dot Matrix, misalnya membuat nota penjualan. Meskipun, tentu saja, bisa juga mencetak PDF langsung di printer tersebut, namun umumnya akan memakan waktu lebih lama dan hasilnya mungkin tidak sebagus jika mencetak file *.txt saja.
Misalnya, ingin membuat dokumen teks seperti berikut
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Toko Terang Gelap Jln. Lampu Senter No 33 Kota Senja ======================================== Nota No. 778899 29/10/2015 11:23:55 ---------------------------------------- Qty Nama Barang Total ---------------------------------------- 1 Item 1 10 2 Item 2 200 3 Item 3 3000 4 Item 4 40000 5 Item 5 500000 ---------------------------------------- Terima Kasih Atas Kunjungan Anda ======================================== |
Perhatikan bahwa dokumen tersebut hanya berupa teks saja, tanpa format yang Rich. Format yang ada hanyalah rata kiri, kanan, dan tengah. Namun format tersebut dapat pula diaplikasikan di dalam 1 baris, dengan kolom-kolom seperti tabel.
Format rata kiri, kanan, tengah tersebut sebenarnya hanya dihasilkan dengan jumlah spasi yang tepat agar dalam 1 baris, teks yang diinginkan dapat diletakkan di bagian yang sesuai.
Kembali ke topik tentang penggunaan Java untuk membuat dokumen seperti ini. Dokumen diatas dihasilkan dengan script Java berikut ini
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | public static void main(String[] args){ LineFormatter lf = new LineFormatter(40); lf.addLine("Toko Terang Gelap", LineFormatter.CENTER_ALIGN); lf.addLine("Jln. Lampu Senter No 33", LineFormatter.CENTER_ALIGN); lf.addLine("Kota Senja", LineFormatter.CENTER_ALIGN); lf.addDivider("="); lf.addLine( new LineColumn("Nota No. 778899", 20) .addColumn("29/10/2015 11:23:55", 20, LineFormatter.RIGHT_ALIGN) ); lf.addDivider("-"); lf.addLine( new LineColumn("Qty", 5, LineFormatter.CENTER_ALIGN) .addColumn("Nama Barang", 25, LineFormatter.CENTER_ALIGN) .addColumn("Total", 10, LineFormatter.CENTER_ALIGN) ); lf.addDivider("-"); for(int i = 1; i <= 5; i++){ lf.addLine( new LineColumn(i + " ", 5, LineFormatter.CENTER_ALIGN) .addColumn("Item " + i, 25) .addColumn("" + (i * ((int)Math.pow(10, i))), 10, LineFormatter.RIGHT_ALIGN) ); } lf.addDivider("-"); lf.addLine("Terima Kasih", LineFormatter.CENTER_ALIGN); lf.addLine("Atas Kunjungan Anda", LineFormatter.CENTER_ALIGN); lf.addDivider("="); System.out.println( lf.render() ); } |
Disini, yang saya gunakan adalah class LineFormatter
dan LineColumn
.
LineFormatter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | package gaisma.components.plaintext; import gaisma.Params; import java.util.ArrayList; import java.util.List; /** * Created with IntelliJ IDEA. * User: lee * Date: 11/29/13 * Time: 9:28 PM * <p/> * Java Plain Text Line Formatter */ public class LineFormatter { public static final int LEFT_ALIGN = -1; public static final int CENTER_ALIGN = 0; public static final int RIGHT_ALIGN = 1; private int lineWidth; private List<String> lines; private String newLine = System.getProperty("line.separator"); public static String LEFT_MARGIN = ""; // nothing /** * Initialize LineFormatter with line width initialized as 40 (epson POS printer) */ public LineFormatter() { init(40); } /** * Initialize LineFormatter with specified line width * * @param l : line width */ public LineFormatter(int l) { init(l); } /** * Set new line character, this is not necessary as LineFormatter automatically detect System new line character * * @param n : new line character * @return current LineFormatter instance */ public LineFormatter setNewLine(String n) { this.newLine = n; return this; } private void init(int l) { this.lineWidth = l; lines = new ArrayList<String>(); } /** * add new line * * @param cols LineColumn Class instance from whose columns constructed as line * @return current LineFormatter instance */ public LineFormatter addLine(LineColumn cols) { return addLine(cols.getLine()); } /** * add new line, with LineFormatter.LEFT_ALIGN * * @param s line to be added * @return current LineFormatter instance */ public LineFormatter addLine(String s) { return addLine(s, LEFT_ALIGN); } /** * add new line, with specified alignment * * @param s line to be added * @param align * @return current LineFormatter instance */ public LineFormatter addLine(String s, int align) { switch (align) { case LEFT_ALIGN: return saveLine(String.format("%-" + this.lineWidth + "s", s)); case RIGHT_ALIGN: return saveLine(String.format("%" + this.lineWidth + "s", s)); case CENTER_ALIGN: int sw = s.length(); int pad = (this.lineWidth - sw) / 2; String l = String.format("%" + pad + "s%s%" + pad + "s", "", s, ""); return addLine(l, RIGHT_ALIGN); } return null; } private LineFormatter saveLine(String s) { if (s.length() > this.lineWidth) s = s.substring(0, this.lineWidth); this.lines.add(LEFT_MARGIN + s); return this; } /** * add blank line * * @return current LineFormatter instance */ public LineFormatter addDivider() { return addLine(" "); } /** * add line with repeated character * * @param s single string to be repeated * @return current LineFormatter instance */ public LineFormatter addDivider(String s) { return addLine( String.format("%" + lineWidth + "s", s) .replace(' ', s.charAt(0)) ); } /** * produce formatted lines * * @return rendered string */ public String render() { String text = ""; if (lines.size() > 0) { text = lines.get(0); } for (int i = 1; i < lines.size(); i++) { text += this.newLine + lines.get(i); } return text; } /** * clear all buffered line * * @return current LineFormatter instance */ public LineFormatter reset() { lines.clear(); return this; } } |
LineColumn.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | package gaisma.components.plaintext; import java.util.ArrayList; import java.util.List; /** * Created with IntelliJ IDEA. * User: lee * Date: 11/29/13 * Time: 9:39 PM */ public class LineColumn { private List<String> columns = new ArrayList<String>(); public LineColumn(){ } public LineColumn(String s, int width){ this.addColumn(s, width); } public LineColumn addBlankSpace(int width){ return this.addColumn(" ", width); } public LineColumn(String s, int width, int align){ addColumn(s, width, align); } public LineColumn addColumn(String s, int width){ return addColumn(s, width, LineFormatter.LEFT_ALIGN); } public LineColumn addColumn(String s, int width, int align){ if(s.length() > width) s = s.substring(0, width); switch (align){ case LineFormatter.LEFT_ALIGN: columns.add(String.format("%-" + width + "s", s)); break; case LineFormatter.RIGHT_ALIGN: columns.add(String.format("%" + width + "s", s)); break; case LineFormatter.CENTER_ALIGN: int sw = s.length(); int pad = (width - sw) / 2; String l = String.format("%" + pad + "s%s%" + pad + "s", "", s, ""); return addColumn(l, width, LineFormatter.RIGHT_ALIGN); } return this; } public String getLine(){ String line = ""; for(int i = 0; i < columns.size(); i++){ line += columns.get(i); } return line; } } |
LineFormatter adalah class utama yang akan membuat format teks dapat diatur agar ditempatkan dalam format rata kiri, kanan, atau tengah. Sedangkan LineColumn, berguna agar dalam 1 baris, dapat dibuat beberapa kolom, yang masing-masing kolom dapat diberikan format sendiri sendiri.
Dua class ini saya buat karena punya kebutuhan membuat dokumen teks sederhana, dan aplikasinya sendiri diusahakan agar dapat berukuran sekecil-kecilnya. Pencarian singkat di Google tidak membuahkan hasil library yang sesuai, dan alasan itulah yang membuat saya menciptakan library ini.
Atau mungkin Anda tahu Library yang lain? Comment ya.
Terima kasih, semoga bisa berguna untuk kita semua.
Menonaktifkan PHP di folder tertentu
Terkadang kita perlu untuk menonaktifkan file dengan ektensi *.php di folder tertentu di website kita. Misalnya saja, pada instalasi WordPress, pada folder wp-content/wp-uploads, terkadang kita perlu memastikan bahwa user tidak dapat mengupload file *.php dan melakukan eksekusi file php tersebut.
Tapi pertanyaannya, bukankah kita tinggal membatasi jenis file yang boleh diupload? Betul, wordpress memang dapat membatasi jenis file yang dianggap “berbahaya” agar tidak dapat diupload.
Tapi bagaimana jika user tetap nakal dan mengupload file tersebut melalui FTP ? Gampang, jangan berikan akses write folder pada user. Namuun, dalam kasus tertentu, hal ini tidak dapat dilakukan.
Namun bagaimanapun juga, apapun alasan penggunaannya, berikut ada cara sederhana menonaktifkan script php dalam suatu folder.
Dalam contoh ini, kita akan menggunakan file .htaccess
yang akan diletakan di folder yang ingin dinonaktifkan file php nya. Tentu saja, dengan asumsi Server Apache yang digunakan telah dikonfigurasi untuk membaca file .htaccess
ini, yang mana, pada umumnya, memang sudah dikonfigurasi begitu.
Isikan baris berikut pada file .htaccess tersebut,
1 | php_flag engine off |
Atau jika Anda menggunakan PHP-CGI, bisa dengan mengisikan script berikut di .htaccess
1 2 3 4 | <FilesMatch \.php$> SetHandler None ForceType text/plain </FilesMatch> |
Maka, file *.php di folder tersebut akan disajikan sebagai teks biasa saja, dan script php di dalamnya tidak akan dieksekusi.
SQL: filter data berdasarkan beberapa baris data
Post kali ini, saya ingin membahas contoh kasus yang ditanyakan di stackoverflow.
Dimana pertanyaan inti-nya adalah, bagaimana menampilkan data post
yang memiliki relasi terhadap tag
dalam table relasi
, namun yang diinginkan adalah melakukan filter post yang memiliki beberapa tag, bukan hanya tag tertentu saja.
Misalnya,
- post “Hallo Dunia” memiliki tag “tag1”
- post “Apa Kabar” memiliki tag “tag2”
- post “Pilih Saya” memiliki tag “tag1” DAN “tag2”
Nah, yang diinginkan adalah menampilkan post yang memiliki 2 tag “tag1” dan “tag2”. Bukan salah satu tag saja, di contoh di atas, akan muncul post “Pilih Saya”.
Saya mendesain ulang contoh tabel yang digunakan seperti di bawah ini.
Table yang digunakan
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | konglie=# \d List OF relations Schema | Name | TYPE | Owner --------+-----------------+-------+--------- public | ppost | TABLE | konglie public | ptags | TABLE | konglie public | rel_ppost_ptags | TABLE | konglie (3 ROWS) konglie=# \d ppost TABLE "public.ppost" COLUMN | TYPE | Modifiers --------+-----------------------+----------- pid | INTEGER | pname | CHARACTER VARYING(20) | konglie=# \d ptags TABLE "public.ptags" COLUMN | TYPE | Modifiers --------+-----------------------+----------- tid | INTEGER | tname | CHARACTER VARYING(20) | konglie=# \d rel_ppost_ptags TABLE "public.rel_ppost_ptags" COLUMN | TYPE | Modifiers --------+---------+----------- pid | INTEGER | tid | INTEGER | |
Sample Data
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | konglie=# SELECT * FROM ppost ; pid | pname -----+-------- 100 | post 1 101 | post 2 102 | post 3 (3 ROWS) konglie=# SELECT * FROM ptags ; tid | tname ------+------- 1000 | tag1 1001 | tag2 1002 | tag3 1004 | tag5 1005 | tag6 1003 | tag4 (6 ROWS) konglie=# SELECT * FROM rel_ppost_ptags ; pid | tid -----+------ 100 | 1000 * 100 | 1001 * 100 | 1003 * 101 | 1000 ** 101 | 1001 ** 102 | 1001 102 | 1002 102 | 1001 101 | 1001 101 | 1003 ** 102 | 1001 (11 ROWS) |
Data yang diinginkan adalah bagaimana mengambil data atau post, yang memiliki beberapa tag tertentu. Misalnya, tampilkan data post yang memiliki tag tag1
,tag2
, dan tag4
. Data yang hanya memiliki salah satu tag tersebut tidak ikut ditampilkan. Hanya post yang memiliki ketiga tag tersebut saja, yang akan ditampilkan.
Dalam contoh ini, post yang diinginkan adalah post dengan pid 100 dan 101, perhatikan yang diberi tanda *
dan **
di atas.
Solusi yang terpikirkan adalah sebagai berikut.
1. Tentukan tid
dari tag yang diinginkan, dalam contoh ini, adalah mengambil tid
dari table ptags
berdasarkan tname
.
1 2 3 4 5 6 7 | konglie=# SELECT tid FROM ptags WHERE tname IN ('tag1', 'tag2', 'tag4'); tid ------ 1000 1001 1003 (3 ROWS) |
2. Kumpulkan terlebih dahulu seluruh post yang memiliki tag tag yang diinginkan. Sampai tahap ini, post dengan tag yang tidak lengkap pun akan dimunculkan.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | konglie=# SELECT pid, tid FROM rel_ppost_ptags WHERE tid IN ( SELECT tid FROM ptags WHERE tname IN ('tag1', 'tag2', 'tag4' ) ); pid | tid -----+------ 100 | 1000 100 | 1001 100 | 1003 101 | 1000 101 | 1001 102 | 1001 * 102 | 1001 * 101 | 1001 101 | 1003 102 | 1001 * (10 ROWS) |
Perhatikan baris diberi tanda *
, yang merupakan data-data yang terduplikasi. Sebenarnya data ini hanya memberi contoh saja, dalam kenyataannya, seharusnya hal ini tidak akan terjadi, dan table rel_ppost_ptags
akan lebih baik jika memberikan batasan UNIQUE
atau PRIMARY KEY
pada 2 field, pid
dan tid
. Sehingga tidak akan ada data yang menduplikasi pid dan tid secara bersamaan.
Untuk itu, akan kita tambahkan keyword distinct
1 2 3 4 5 6 7 8 9 10 11 | konglie=# SELECT DISTINCT pid, tid FROM rel_ppost_ptags WHERE tid IN ( SELECT tid FROM ptags WHERE tname IN ('tag1', 'tag2', 'tag4' ) ); pid | tid -----+------ 100 | 1001 100 | 1003 102 | 1001 101 | 1000 100 | 1000 101 | 1001 101 | 1003 (7 ROWS) |
Dengan distinct
, baris baris yang terduplikasi akan dihilangkan.
3. Hitung jumlah data berdasarkan pid
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | konglie=# SELECT pid, COUNT(*) FROM ( SELECT DISTINCT pid, tid FROM rel_ppost_ptags WHERE tid IN ( SELECT tid FROM ptags WHERE tname IN ('tag1', 'tag2', 'tag4' ) ) ) tmp GROUP BY pid; pid | COUNT -----+------- 101 | 3 100 | 3 102 | 1 (3 ROWS) |
4. Pada langkah kedua, kita sudah menampilkan data pid
dan tid
sesuai dengan tag yang kita inginkan, hanya saja belum menentukan apakah sebuah pid
memiliki semua kriteria tag yang kita inginkan. Namun, kita dapat pastikan bahwa, apabila pid tersebut memiliki semua tag yang kita inginkan, maka jumlah pid dari hasil sql tersebut akan ada sebanyak n
buah, dimana n
adalah jumlah tag yang kita inginkan, dalam contoh ini adalah 3. Nah, pada langkah di atas, kita sudah menghitung jumlah pid yang ada, langkah terakhir ini hanya memfilter semuah pid yang berjumlah n
tadi saja, dengan memberikan keyword having
.
konglie=# select pid, count(*) from ( select distinct pid, tid from rel_ppost_ptags where tid in ( select tid from ptags where tname in ('tag1', 'tag2', 'tag4' ) ) ) tmp group by pid having count(*) = 3; pid | count -----+------- 101 | 3 100 | 3 (2 rows)
Dengan demikian, kita sudah dapat memfilter post yang memiliki tag-tag tertentu secara keseluruhan, bukan hanya memiliki salah satu tag saja.
Sebagai tambahan informasi, sql di atas diujicobakan menggunakan Database PostgreSQL 9.4, namun saya rasa tidak ada fungsi spesific database di atas sehingga besar kemungkinan akan dapat digunakan di database server lainnya.
Semoga bermanfaat.
Java Swing, tampilan Calculator dengan GridBagLayout
Post kali ini, saya memberikan source code untuk membangun tampilan Calculator dengan Java Swing, menggunakan GridBagLayout. Continue Reading…
Menggambar Monas
Post ini sebenarnya bukan berisi tutorial atau sejenisnya. Hanya sekedar penasaran aja. Ada kenalan yang bertanya mengenai algoritma pemrograman menggambar Monas dengan barisan karakter bintang ‘*’. Continue Reading…