Jumat, 29 Agustus 2025

Concat tidak berfungsi untuk indexing

 $sql = "SELECT a.* , CONCAT(a.Kode_Barang,'<br><b>',b.Nm_Aset5,'</b>') as Nm_Aset5, CONCAT(a.latitude,'<br>',a.longitude) as latitude, c.Uraian as Kondisi from ta_kib_c as a left join ref_rek5_108 as b on CONCAT(a.Kd_Aset8,a.Kd_Aset80,a.Kd_Aset81,a.Kd_Aset82,a.Kd_Aset83,a.Kd_Aset84,a.Kd_Aset85)=CONCAT(b.Kd_Aset,b.Kd_Aset0,b.Kd_Aset1,b.Kd_Aset2,b.Kd_Aset3,b.Kd_Aset4,b.Kd_Aset5) LEFT JOIN ref_kondisi as c on a.Kondisi=c.Kd_Kondisi";  

Dari query Anda, ada beberapa hal yang bikin lambat saat data ratusan ribu baris:

  1. Pakai SELECT a.* → ini ambil semua kolom, padahal tidak semuanya dipakai.

  2. Pakai CONCAT(...) di JOIN dan WHERE → ini bikin index di tabel tidak bisa dipakai (selalu full scan).

  3. Search LIKE "%keyword%" ke semua kolom → ini berat sekali kalau tabel besar, apalagi tanpa index.

  4. Hitung total pakai query lengkap → harusnya cukup COUNT(*) dengan kondisi filter.


✨ Perbaikan Step by Step

1. Pilih hanya kolom yang dipakai

Misalnya:

SELECT a.ID, a.Kode_Barang, a.Tgl_Perolehan, a.Harga, CONCAT(a.Kode_Barang,'<br><b>',b.Nm_Aset5,'</b>') AS Nm_Aset5, CONCAT(a.latitude,'<br>',a.longitude) AS latitude, c.Uraian AS Kondisi

➡️ jangan SELECT a.*.


2. Hindari CONCAT() di JOIN

Anda punya ini:

ON CONCAT(a.Kd_Aset8,a.Kd_Aset80,a.Kd_Aset81,a.Kd_Aset82,a.Kd_Aset83,a.Kd_Aset84,a.Kd_Aset85) = CONCAT(b.Kd_Aset,b.Kd_Aset0,b.Kd_Aset1,b.Kd_Aset2,b.Kd_Aset3,b.Kd_Aset4,b.Kd_Aset5)

⚡ Ini bikin MySQL tidak bisa pakai index.
Lebih cepat kalau dibandingkan per kolom:

ON a.Kd_Aset8 = b.Kd_Aset AND a.Kd_Aset80 = b.Kd_Aset0 AND a.Kd_Aset81 = b.Kd_Aset1 AND a.Kd_Aset82 = b.Kd_Aset2 AND a.Kd_Aset83 = b.Kd_Aset3 AND a.Kd_Aset84 = b.Kd_Aset4 AND a.Kd_Aset85 = b.Kd_Aset5

3. Hindari CONCAT di filter OPD

Anda tulis:

WHERE CONCAT(a.Kd_Bidang,a.Kd_Unit) = '$a1'

Lebih cepat kalau pakai AND:

WHERE a.Kd_Bidang = '$kd_bidang' AND a.Kd_Unit = '$kd_unit'

Kalau $a1 isinya gabungan, sebaiknya pecah dulu di PHP (substr atau explode) baru masukkan ke query.


4. Optimalkan search

Sekarang search Anda looping semua kolom:

for ($i=0; $i<count($columns); $i++) { $where_sql .= $columns[$i].' LIKE "%'.$search.'%"'; }

➡️ ini berat kalau kolom banyak.

Solusi:

  • Batasi ke beberapa kolom penting (misalnya kode barang, nama aset, kondisi).

  • Gunakan FULLTEXT INDEX kalau banyak teks.

Contoh:

WHERE (a.Kode_Barang LIKE '%$search%' OR b.Nm_Aset5 LIKE '%$search%')

5. Hitung total dengan COUNT(*)

Sekarang Anda pakai:

$count = $database->query($sql); $totaldata = $count->num_rows;

➡️ ini jalankan query penuh (dengan join dan limit hilang).

Lebih baik:

$sqlCount = "SELECT COUNT(*) FROM ta_kib_c a LEFT JOIN ref_rek5_108 b ON ... LEFT JOIN ref_kondisi c ON ... $whereClause"; $totaldata = $database->query($sqlCount)->fetch_row()[0];

🚀 Contoh Query yang Lebih Cepat

$sql = "SELECT a.ID, a.Kode_Barang, a.Tgl_Perolehan, a.Harga, CONCAT(a.Kode_Barang,'<br><b>',b.Nm_Aset5,'</b>') AS Nm_Aset5, CONCAT(a.latitude,'<br>',a.longitude) AS latitude, c.Uraian AS Kondisi FROM ta_kib_c AS a LEFT JOIN ref_rek5_108 AS b ON a.Kd_Aset8 = b.Kd_Aset AND a.Kd_Aset80 = b.Kd_Aset0 AND a.Kd_Aset81 = b.Kd_Aset1 AND a.Kd_Aset82 = b.Kd_Aset2 AND a.Kd_Aset83 = b.Kd_Aset3 AND a.Kd_Aset84 = b.Kd_Aset4 AND a.Kd_Aset85 = b.Kd_Aset5 LEFT JOIN ref_kondisi AS c ON a.Kondisi = c.Kd_Kondisi WHERE 1=1"; // filter dinamis if ($kd_KA != '') { $sql .= " AND a.Kd_KA = '$kd_KA'"; } if ($parameter == '1') { $sql .= " AND YEAR(a.Tgl_Perolehan) <= '$thn'"; } elseif ($parameter == '2') { $sql .= " AND YEAR(a.Tgl_Perolehan) = '$thn'"; } // filter OPD if ($a1 != '0' && $a2 == '0') { $sql .= " AND a.Kd_Bidang = '".substr($a1,0,2)."' AND a.Kd_Unit = '".substr($a1,2,2)."'"; } elseif ($a2 != '0' && $a3 == '0') { $sql .= " AND a.Kd_Bidang = '".substr($a2,0,2)."' AND a.Kd_Unit = '".substr($a2,2,2)."' AND a.Kd_Sub = '".substr($a2,4,2)."'"; } elseif ($a3 != '0') { $sql .= " AND a.Kd_Bidang = '".substr($a3,0,2)."' AND a.Kd_Unit = '".substr($a3,2,2)."' AND a.Kd_Sub = '".substr($a3,4,2)."' AND a.Kd_UPB = '".substr($a3,6,2)."'"; } // search if (!empty($_GET['search']['value'])) { $search = $_GET['search']['value']; $sql .= " AND (a.Kode_Barang LIKE '%$search%' OR b.Nm_Aset5 LIKE '%$search%' OR c.Uraian LIKE '%$search%')"; } // order $sortColumn = $columns[$_GET['order'][0]['column']]; $sortDir = $_GET['order'][0]['dir']; $sql .= " ORDER BY $sortColumn $sortDir LIMIT $start, $length";

⚡ Dengan ini:

  • Index bisa dipakai (JOIN & WHERE tidak pakai CONCAT).

  • Query count lebih ringan (COUNT(*)).

  • Search lebih efisien (hanya kolom penting).


Mau saya bikinkan versi full siap pakai (PHP lengkap dengan JSON response untuk DataTables) biar tinggal copy-paste ke load-data.php Anda?

Kamis, 28 Agustus 2025

Menambahkan field diluar field tabel pada datatable

if (isset($_GET['search']['value']) && $_GET['search']['value'] != '') {


    $search = $_GET['search']['value'];

    $where_sql .= ' (';

    // create parameter pencarian kesemua kolom yang tertulis

    // di $columns

    for ($i = 0; $i < count($columns); $i++) {

        if ($columns[$i] != 'Kapitalisasi') {

            $where_sql .= $columns[$i] . ' LIKE "%' . $search . '%" ';

        }


        // agar tidak menambahkan 'OR' diakhir Looping

        if ($i < count($columns) - 2) {

            $where_sql .= ' OR ';

        }

        // echo $where_sql;

    }


    $where_sql  .= ' )';

}

// die();


// echo $where_sql;

if (count($where) > 0) {

    $where = join(" and ", $where);

    $where = "where $where ";

} else {

    $where = '';

}

if ($where_sql != '') {

    $sql .= " $where AND $where_sql";

} else {

    $sql .= " $where";

Selasa, 26 Agustus 2025

Membuat query untuk menampilkan data yang tidak ada pada tabel relasi

 SELECT a.*,

       b.Nm_Aset5 AS Nm_Aset5,

       CONCAT(a.latitude, '<br>', a.longitude) AS latitude,

       c.Uraian AS Kondisi

FROM ta_kib_c AS a

LEFT JOIN ref_rek5_108 AS b 

       ON CONCAT(a.Kd_Aset8,a.Kd_Aset80,a.Kd_Aset81,a.Kd_Aset82,a.Kd_Aset83,a.Kd_Aset84,a.Kd_Aset85) 

       = CONCAT(b.Kd_Aset,b.Kd_Aset0,b.Kd_Aset1,b.Kd_Aset2,b.Kd_Aset3,b.Kd_Aset4,b.Kd_Aset5)

LEFT JOIN ref_kondisi AS c 

       ON a.Kondisi = c.Kd_Kondisi

LEFT JOIN ta_kibcr AS d 

       ON d.IDPemda = a.IDPemda

WHERE  d.IDPemda IS NULL

Selasa, 19 Agustus 2025

menambahkan CSS untuk type file

 <style>

/* Bungkus input file */

.custom-file {

    position: relative;

    display: inline-block;

    width: 100%;

    max-width: 400px;

}


/* Hilangkan tampilan default */

.custom-file input[type="file"] {

    position: absolute;

    left: 0;

    top: 0;

    opacity: 0;

    width: 100%;

    height: 100%;

    cursor: pointer;

}


/* Tombol custom */

.custom-file-label {

    display: flex;

    align-items: center;

    justify-content: space-between;

    background: #f8f9fa;

    border: 1px solid #ced4da;

    border-radius: 8px;

    padding: 10px 15px;

    font-size: 14px;

    color: #495057;

    cursor: pointer;

    transition: all 0.2s ease-in-out;

}


/* Hover effect */

.custom-file-label:hover {

    background: #e9ecef;

    border-color: #adb5bd;

}


/* Nama file tampil */

.file-name {

    font-style: italic;

    color: #6c757d;

    margin-left: 10px;

    flex: 1;

    white-space: nowrap;

    overflow: hidden;

    text-overflow: ellipsis;

}

</style>


<div class="custom-file">

    <label for="uploadFile" class="custom-file-label">

        Pilih File <span class="file-name">(*Max 2 MB)</span>

    </label>

    <input type="file" id="uploadFile" name="uploadFile" multiple>

</div>


<script>

document.getElementById("uploadFile").addEventListener("change", function() {

    const files = this.files;

    const maxSize = 2 * 1024 * 1024; // 2 MB

    let fileNames = [];


    for (let i = 0; i < files.length; i++) {

        if (files[i].size > maxSize) {

            alert("File " + files[i].name + " melebihi batas 2 MB!");

            this.value = "";

            document.querySelector(".file-name").textContent = "(*Max 2 MB)";

            return;

        }

        fileNames.push(files[i].name);

    }


    // tampilkan nama file

    document.querySelector(".file-name").textContent = fileNames.join(", ");

});

</script>

Merubah Collation pada database

🔹 Cara aman kalau ada FOREIGN KEY Matikan constraint sementara 

 SET FOREIGN_KEY_CHECKS=0; lalu jalankan semua 
ALTER TABLE (nama_tabel)  CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; 
 Nyalakan lagi constraint SET FOREIGN_KEY_CHECKS=1;  

Senin, 21 Juli 2025

Bagaimana membuat tampilan title bisa menarik

Pada tampilan konten tabel seringkali datanya terlalu panjang, maka perlu ditampilkan limit text agar tampak rapih. Tetapi kita butuh menampilkan data komplit dari isi tabel tersebut. Untuk itu untuk memenuhi kebutuhan tersebut ditampilkan pada titel dengan menyorotkan kursor pada data dimaksud. Untuk itu saya memberikan contoh kasus pada data riwayat jabatan pada SIMPEG. semisal kolom yang berisi data panjang/banyak adalah kolok nama_jabatan (biasanya berisi nama jabatan, subunit kerja dan unit kerja). Maka untuk menampilkannya seperti dibawah ini : Membuat fungsi limittxt: function limittxt($nama, $limit) { if (strlen($nama) > $limit) { $nama = substr($nama, 0, $limit) . '...'; } else { $nama = $nama; } return $nama; } Membuat css : Kemudian di tampilkan pada tabel :
Demikian contoh untuk menampilkan data yang panjang/banyak agar tampilan tabel bagus.

Selasa, 06 Mei 2025

Melengkapi sweetalert dengan reload halaman

Pada proses simpan, edit dan delete seringkali reload ke halaman yang dituju. Pada sweetalert bisa menambahkan reload setelah proses tersebut. scriptnya seperti dibawah :

Selasa, 22 April 2025

Cara menampilkan data digit ribuan pada datatabel serverside

Untuk menampilkan data nominal ribuan pada datatabel serverside bisa dilakukan dengan membuat dua file php. Yang pertama untuk membuat header tabel, dan yang kedua untuk memanggil data dari database. Misal file pertama search-data.php. scriptnya sebagai berikut : Kemudian kita buat file untuk mengambil data dari database. Misal nama filenya load-data.php. Koneksi database silahkan disesuaikan dan nama tabel, nama field juga disesuaikan dengan tabel yang akan ditampilkan.

Jumat, 07 Februari 2025

Membuat link tombol dengan klik pada baris tabel dengan php

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<table border="1" id="myTable">
    <tr>
        <th>ID</th>
        <th>Nama</th>
        <th>Aksi</th>
    </tr>
    <?php
    foreach ($data as $row) {
        echo '<tr data-href="detail.php?id=' . $row['id'] . '">';
        echo '<td>' . $row['id'] . '</td>';
        echo '<td>' . $row['nama'] . '</td>';
        echo '<td><button>Lihat</button></td>';
        echo '</tr>';
    }
    ?>
</table>

<script>
    $(document).ready(function() {
        $('#myTable tr').click(function() {
            window.location = $(this).data('href');
        });
    });
</script>

Kamis, 16 Januari 2025

Menambahkan field array pada datatables server side

 Terkadang untuk  menambahkan field yang berisi rumus pada SQL implementasi rumit. itu disebabkan karena rumus yang panjang. Untuk itu bisa dilakukan pada script php nya, tidak perlu pada Query SQLnya.


Selasa, 19 November 2024

Beberapa permasalahan pada e-absensi online

Beberapa kali kami disibukkan dengan absensi online yang bermasalah. Baik dari sisi data, server, jaringan dan aplikasi. Kami melakukan beberapa proses pembenahan. Dari pengalaman tersebut kami bisa menyimpulkan :
  1.  Absensi tidak bisa diakses dari jaringan diluar Dinkominfo. Solusinya dengan "allow" pada routes/Juniper 
  2. Database yang besar sehingga load data lama Solusi dengan memberikan value pada Engine database myISam
  3. Untuk baca lebih optimal dg myisam sedang untuk tulis pakai innodb rutin dilakukan OPTIMIZE TABLE nama_tabel; pada tabel2 yang besar. 
 next plan : load balacing untuk DB jadi proses CUD di server master sedang proses R di server slave

Minggu, 08 September 2024

Menggunakan sweetAlert dan Json

Untuk menampilkan data sweetalert pada penyimpanan menggunakan javascript/ajax harus memastikan data response ketika proses query (simpan, ubah, delete) adalah data json. tanpa keluaran yang lain. sebagai contoh : getUpdate($sql); if($result){ $res['success']=true; $res['msg']="Data berhasil dihapus..!! "; }else{ $res['success']=false; $res['msg']="Data gagal dihapus..!! "; } echo json_encode($res); ?> jika di response masih ada body ataupun menyertakan css, maka tidak bisa diproses di javascript. function getUpdateSave() { var formData = $("#formKegiatan").serialize(); // var id = $("#misi").val(); var el = $('#b'); $.ajax({ type: "POST", url: "./modul/subkegiatan/update_save.php", dataType: 'json', data: formData, success: function(item) { // $("#kelurahan").val(item.kdOpd); // $("#kegiatan").val(item.kdKeg); if(item.success==true){ Swal.fire( 'Informasi..!', 'Data berhasil diubah..!', 'success' ); } else{ Swal.fire( 'Informasi..!', 'Data gagal diubah..!', 'error' ); } } }); LoadSearchData(); }

Kamis, 08 Agustus 2024

Menyimpan file pendukung pada form dengan javascript

Untuk menambahkan file pendukung pada form dan menyimpannya dengan javascript membutuhkan script yang berbeda dengan penggunaan serialize. Jika tidak ada form yang bertipe "file" kita bisa menggunakan : var formData = $("#formUniker").serialize(); Tapi jika menggunakan form tipe "file" kita menggunakan append. lihat contoh berikut : untuk proses simpannya sebagai berikut : Demikian contoh untuk penggunaan append pada proses penyimpanan dengan javascript.

Minggu, 21 Juli 2024

Cara membuat separator rupiah pada form input pada PHP

Untuk membuat form dengan separator rupiah pada form text di php : Dan pada simpan harus ditambahkan script str_replace :

Jumat, 12 Juli 2024

Server tidak bisa akses keluar untuk bridging "Permission denied" (Error Code: 7)"

ada beberapa langkah lain yang dapat Anda coba untuk menyelesaikan masalah "Permission denied" (Error Code: 7) saat menggunakan cURL di PHP. 1. Periksa dan Atur Izin Firewall Pastikan firewall di server Anda mengizinkan koneksi keluar ke alamat IP dan port tujuan. Memeriksa Iptables: sh Salin kode sudo iptables -L -v -n Menambahkan Aturan untuk Mengizinkan Koneksi Keluar: sh Salin kode sudo iptables -A OUTPUT -p tcp --dport 8243 -j ACCEPT sudo service iptables save 2. Periksa dan Atur SELinux atau AppArmor Jika SELinux atau AppArmor aktif, pastikan pengaturan mereka mengizinkan skrip PHP membuat koneksi jaringan. Untuk SELinux: sh Salin kode sudo setsebool -P httpd_can_network_connect 1 3. Periksa Konfigurasi Server Web (Apache/Nginx) Pastikan konfigurasi server web Anda mengizinkan skrip PHP untuk membuat koneksi jaringan. Untuk Apache, pastikan modul mod_security atau modul keamanan lainnya tidak mengganggu. Jika perlu, nonaktifkan sementara untuk pengujian. Untuk Nginx, pastikan tidak ada aturan khusus yang membatasi koneksi keluar. 4. Periksa Konfigurasi PHP Pastikan tidak ada fungsi yang diblokir di php.ini yang bisa menyebabkan masalah ini. Periksa disable_functions: sh Salin kode php -i | grep disable_functions Pastikan curl_exec dan fungsi terkait tidak ada dalam daftar fungsi yang dinonaktifkan.

Kamis, 27 Juni 2024

Membuat tombol simpan dengan javascript "onClick"

Membuat formulir input data dengan proses simpan onclick javascript tombol yang digunakan jangan menggunakan submit. Jika menggunakan tipe submit akan mengakibatkan refresh halaman.

Minggu, 21 April 2024

Cara Mengupload Gambar dengan Ajax dan Menyimpan ke Database PHP

Cara Mengupload Gambar/Foto dengan Ajax dan menyimpan ke Database MySQL/MariaDB menggunakan PHP – Hai ketemu lagi dengan saya dewan komputer dan pada kali ini saya akan memposting tentang cara menyimpan foto/gambar ke dalam database dan tentunya saya menggunakan Ajax. Setelah sebelumnya saya mencontohkan cara upload file menggunakan ajax dan tanpa loading, pada contoh kali ini yang beda hanya kita menyimpannya pada database juga. Namun sebenarnya yang tersimpan di database hanya nama filenya saja atau path. Untuk gambar/foto tentunya tersimpan di local storage atau pada server. Kalau gambar disimpan di database bisa sobat bayangkan database sampe bergiga-giga dan jika ingin pindah server pasti tidak akan bisa maka sangat tidak mungkin jika gambar/foto/file disimpan pada databasenya melainkan hanya nama filenya saja sehingga kita bisa mengaturnya pada local storagenya nanti. Caranya mudah tinggal sobat ikuti saja cara dibawah :

Form :

  




Script simpan :

  




Ajax :

  




Minggu, 04 Februari 2024

Migrasi Database Slims Meranti ke Slims Bulians (versi 9)

 Tahun 2024 ini saya membantu teman di salah satu SMP Negeri di Kabupaten Temanggung. Beliau ingin mempublishkan / online kan e-Library yang sudah digunakan dengan Slims Meranti (open source). Tugas itu merupakan keinginan dari Kepala Sekolah agar e-Library bisa di akses dimanapun juga. Tahapan migrasi saya lakukan dengan memperioritaskan installasi Slims Bulian di lokal server. Proses instalasi seperti postingan saya terdahulu.

Kemudian proses selanjutnya adalah migrasi data dari meranti, ternyata untuk proses migrasi membutuhkan waktu yang lumayan lama, karena struktur tabel yang berbeda antara meranti dan bulian. Proses ini saya lakukan satu per satu masing-masing tabel pada database meranti ke database bulian. Beberapa tabel yang berbeda antara lain : biblio, setting, user, system_log.

Apabila tidak dilakukan mapping tabel, maka beberapa proses/modul di Slims bulian tidak bisa berjalan. Setelah beberapa saat melakukan mapping dan kemudian migrasi data bisa berhasil.

Proses selanjutnya adalah uji sistem online. Proses ini dilakukan oleh teman di SMP yang mengetahui proses bisnis dari e-Library. Saya berharap semoga proses bisa berjalan dengan bail\k dan lancar.

Concat tidak berfungsi untuk indexing

 $sql = "SELECT a.* , CONCAT(a.Kode_Barang,'<br><b>',b.Nm_Aset5,'</b>') as Nm_Aset5, CONCAT(a.latitud...