Menggunakan Having dalam MySQL: Panduan Lengkap

Kemaskini terakhir: 24 Mei 2025
Pengarang TecnoDigital
  • Klausa Having menapis kumpulan baris selepas dikumpulkan dengan GROUP BY.
  • Membolehkan anda menggunakan syarat untuk mengagregat fungsi untuk mendapatkan hasil yang tepat.
  • Mengoptimumkan pertanyaan dengan indeks dan sekatan meningkatkan prestasi.
  • Alat seperti EXPLAIN membantu menganalisis dan nyahpepijat pertanyaan.
mempunyai dalam mysql

Adakah anda ingin belajar cara menggunakan klausa Having dalam MySQL untuk mengoptimumkan pertanyaan anda dan mendapatkan hasil yang lebih tepat? Mencari cara untuk meningkatkan kemahiran pangkalan data anda ke peringkat seterusnya? Anda telah datang ke tempat yang betul!

Di sini kami menunjukkan kepada anda cara yang berkesan untuk memanfaatkan sepenuhnya alat berkuasa ini. Klausa Having ialah ciri penting dalam MySQL yang membolehkan anda menapis dan menganalisis data terkumpul dengan cekap. Dengan Having, anda boleh menggunakan syarat kompleks pada hasil pertanyaan anda, memberikan anda kawalan tepat ke atas maklumat yang ingin anda dapatkan.

Bayangkan anda mempunyai pangkalan data jualan dan anda perlu mendapatkan pandangan berharga tentang prestasi produk anda atau pembahagian pelanggan anda. Dengan klausa Mempunyai, anda boleh mengumpulkan data anda mengikut kriteria tertentu dan kemudian menapis kumpulan tersebut untuk mendapatkan hasil yang lebih bermakna. Contohnya, anda boleh mendapatkan kategori produk yang telah menjana jumlah jualan melebihi ambang tertentu atau mengenal pasti pelanggan yang telah membuat bilangan pembelian minimum dalam tempoh tertentu.

Pengenalan kepada Mempunyai Klausa dalam MySQL

Bayangkan anda mempunyai pangkalan data jualan dan anda ingin mendapatkan maklumat tentang produk yang telah menghasilkan jumlah jualan melebihi ambang tertentu. Di sinilah klausa Mempunyai memainkan peranan. Anda boleh mengumpulkan jualan mengikut produk dan kemudian menggunakan Having untuk menapis hanya produk yang jumlah jualannya melebihi ambang yang dikehendaki.

SELECT columna1, columna2, ..., función_agregado(columna)
FROM tabla
GROUP BY columna1, columna2, ...
HAVING condición;

Perbezaan antara WHERE dan HAVING

SELECT categoria, SUM(ventas) AS total_ventas
FROM productos
WHERE precio > 100
GROUP BY categoria
HAVING SUM(ventas) > 1000;

Berikut adalah beberapa peraturan umum untuk menentukan bila hendak menggunakan WHERE atau Having :

  • Gunakan WHERE untuk menapis baris individu sebelum mengumpulkan.
  • Gunakan Having untuk menapis kumpulan baris selepas mengumpulkan.
  • WHERE tidak boleh merujuk kepada fungsi agregat, manakala Having boleh.
  • Anda boleh menggunakan kedua-dua WHERE dan Having dalam pertanyaan yang sama jika perlu.

Memahami perbezaan antara WHERE dan Having akan membolehkan anda menulis pertanyaan yang lebih tepat dan cekap, dengan memanfaatkan sepenuhnya keupayaan penapisan MySQL.

Penggunaan asas Having

SELECT columna1, columna2, ..., función_agregado(columna)
FROM tabla
GROUP BY columna1, columna2, ...
HAVING condición;
SELECT id_producto, SUM(cantidad) AS total_vendido
FROM ventas
GROUP BY id_producto
HAVING SUM(cantidad) > 100;
SELECT id_producto, SUM(cantidad) AS total_vendido
FROM ventas
GROUP BY id_producto
HAVING SUM(cantidad) > 100 AND SUM(cantidad) < 500;

Menggabungkan Having dengan fungsi agregat

  • SUM: Mengira jumlah nilai dalam lajur.
  • COUNT: Mengira bilangan baris atau nilai bukan nol dalam lajur.
  • AVG: Mengira purata nilai dalam lajur.
  • MAX: Mengembalikan nilai maksimum dalam lajur.
  • MIN: Mengembalikan nilai minimum lajur.
  1. Dapatkan pelanggan yang purata pembeliannya melebihi $100:
SELECT id_cliente, AVG(total) AS promedio_compras
FROM pedidos
GROUP BY id_cliente
HAVING AVG(total) > 100;
  1. Kira bilangan pesanan bagi setiap pelanggan dan tunjukkan hanya yang mempunyai lebih daripada 5 pesanan:
SELECT id_cliente, COUNT(*) AS total_pedidos
FROM pedidos
GROUP BY id_cliente
HAVING COUNT(*) > 5;
  1. Dapatkan produk yang harga maksimumnya kurang daripada $50:
SELECT id_producto, MAX(precio) AS precio_maximo
FROM productos
GROUP BY id_producto
HAVING MAX(precio) < 50;
  1. Paparkan kategori produk dengan jumlah jualan melebihi $10,000:
SELECT categoria, SUM(total) AS total_ventas
FROM ventas
GROUP BY categoria
HAVING SUM(total) > 10000;
SELECT categoria, SUM(total) AS total_ventas, AVG(precio) AS precio_promedio
FROM ventas
GROUP BY categoria
HAVING SUM(total) > 10000 AND AVG(precio) < 50;

Penapisan bersyarat dengan Having

  • KES: Membolehkan anda mencipta ungkapan bersyarat dengan berbilang syarat dan hasil.
  • IF: Menilai keadaan dan mengembalikan satu nilai jika ia dipenuhi dan nilai lain jika ia tidak dipenuhi.
  • Operator logik (DAN, ATAU, BUKAN): Gabungkan berbilang keadaan untuk mencipta ungkapan logik yang lebih kompleks.
  1. Dapatkan kategori produk dengan jumlah jualan melebihi 10,000 sahaja untuk produk dengan harga lebih daripada 50:
SELECT categoria, SUM(total_ventas) AS total_ventas
FROM ventas
WHERE precio > 50
GROUP BY categoria
HAVING SUM(total_ventas) > 10000;
  1. Paparkan pelanggan dengan purata jumlah pembelian lebih daripada $100 bagi mereka yang telah membuat lebih daripada 5 pesanan:
SELECT id_cliente, AVG(total) AS promedio_compras
FROM pedidos
GROUP BY id_cliente
HAVING AVG(total) > 100 AND COUNT(*) > 5;
  1. Dapatkan kategori produk dengan jumlah jualan lebih daripada 10,000 dan klasifikasikannya sebagai "Tinggi" jika jumlahnya lebih daripada 50,000, "Sederhana" jika antara 20,000 dan 50,000 dan "Rendah" sebaliknya:
SELECT 
    categoria,
    SUM(total_ventas) AS total_ventas,
    CASE 
        WHEN SUM(total_ventas) > 50000 THEN 'Alto'
        WHEN SUM(total_ventas) BETWEEN 20000 AND 50000 THEN 'Medio'
        ELSE 'Bajo'
    END AS clasificacion
FROM ventas
GROUP BY categoria
HAVING SUM(total_ventas) > 10000;
  1. Tunjukkan produk yang harga puratanya melebihi $100 hanya jika mereka mempunyai jualan dalam 30 hari yang lalu:
SELECT 
    id_producto,
    AVG(precio) AS precio_promedio
FROM ventas
WHERE fecha >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
GROUP BY id_producto
HAVING AVG(precio) > 100;
SELECT 
    categoria,
    SUM(total) AS total_ventas
FROM ventas
GROUP BY categoria
HAVING SUM(total) > (
    SELECT AVG(total_ventas)
    FROM (
        SELECT categoria, SUM(total) AS total_ventas
        FROM ventas
        GROUP BY categoria
    ) AS subconsulta
);

Contoh praktikal pertanyaan dengan Having

  1. Dapatkan jabatan yang mempunyai lebih daripada 5 pekerja dan paparkan purata gaji bagi setiap jabatan:
SELECT 
    departamento,
    COUNT(*) AS total_empleados,
    AVG(salario) AS salario_promedio
FROM empleados
GROUP BY departamento
HAVING COUNT(*) > 5;
  1. Paparkan kategori produk dengan jumlah jualan melebihi $10,000 dan margin keuntungan lebih daripada 20%:
SELECT 
    categoria,
    SUM(total) AS total_ventas,
    (SUM(total) - SUM(costo)) / SUM(total) AS margen_ganancia
FROM ventas
GROUP BY categoria
HAVING 
    SUM(total) > 10000 
    AND (SUM(total) - SUM(costo)) / SUM(total) > 0.2;
  1. Dapatkan pelanggan yang telah membuat pembelian dalam sekurang-kurangnya 3 kategori berbeza dan jumlah pembelian mereka melebihi $1,000:
SELECT 
    id_cliente,
    COUNT(DISTINCT categoria) AS total_categorias,
    SUM(total) AS total_compras
FROM ventas
GROUP BY id_cliente
HAVING 
    COUNT(DISTINCT categoria) >= 3 
    AND SUM(total) > 1000;
  1. Tunjukkan produk dengan penilaian purata lebih daripada 4.5 dan yang telah menerima sekurang-kurangnya 10 penilaian:
SELECT 
    id_producto,
    AVG(calificacion) AS promedio_calificacion,
    COUNT(*) AS total_calificaciones
FROM calificaciones
GROUP BY id_producto
HAVING 
    AVG(calificacion) > 4.5 
    AND COUNT(*) >= 10;
  1. Dapatkan kedai dengan jumlah jualan lebih tinggi daripada purata jualan semua kedai dalam 30 hari yang lalu:
SELECT 
    id_tienda,
    SUM(total) AS total_ventas
FROM ventas
WHERE fecha >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
GROUP BY id_tienda
HAVING 
    SUM(total) > (
        SELECT AVG(total_ventas)
        FROM (
            SELECT id_tienda, SUM(total) AS total_ventas
            FROM ventas
            WHERE fecha >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
            GROUP BY id_tienda
        ) AS subconsulta
    );
kumpulan oleh mysql dengan contoh
Artikel berkaitan:
MySQL GROUP BY Penyata dengan Contoh

Pengoptimuman Prestasi dengan Having dalam MySQL

  1. Gunakan indeks yang sesuai:
    • Pastikan anda mempunyai indeks pada lajur yang digunakan dalam klausa KUMPULAN OLEH dan dalam lajur yang terlibat dalam syarat klausa Mempunyai.
    • Indeks boleh meningkatkan prestasi dengan ketara dengan mengurangkan jumlah data yang mesti diperiksa oleh MySQL untuk melaksanakan pengelompokan.
  2. Elakkan pengiraan yang tidak perlu dalam Mempunyai:
    • Jika boleh, cuba lakukan pengiraan dan penapisan dalam klausa WHERE sebelum mengumpulkan.
    • Menapis baris individu sebelum mengumpulkan boleh mengurangkan jumlah data yang diproses dalam klausa Having, yang meningkatkan prestasi.
  3. Gunakan subkueri atau jadual sementara:
    • Dalam sesetengah kes, mungkin lebih cekap untuk menggunakan subkueri atau jadual sementara untuk melakukan pengiraan perantaraan sebelum menggunakan klausa Mempunyai.
    • Ini boleh mengelakkan keperluan untuk pengiraan berulang dan mengurangkan kerumitan pertanyaan utama.
  4. Optimumkan fungsi agregat:
    • Gunakan fungsi agregat yang sesuai dengan keperluan anda. Contohnya, jika anda hanya perlu mengira bilangan baris, gunakan COUNT(*) dan bukannya COUNT(lajur).
    • Elakkan menggunakan fungsi agregat yang tidak perlu atau berlebihan dalam klausa Having.
  5. Hadkan bilangan kumpulan:
    • Jika boleh, cuba hadkan bilangan kumpulan yang dijana oleh klausa GROUP BY.
    • Semakin sedikit kumpulan yang dijana, semakin sedikit pengiraan dan perbandingan yang dilakukan dalam klausa Having, yang meningkatkan prestasi.
  6. Gunakan EXPLAIN untuk menganalisis pelan pelaksanaan:
    • Gunakan pernyataan EXPLAIN sebelum pertanyaan anda untuk mendapatkan maklumat tentang cara MySQL merancang untuk melaksanakannya.
    • Menganalisis pelan pelaksanaan untuk mengenal pasti kesesakan atau kawasan yang berpotensi untuk diperbaiki, seperti indeks yang hilang atau penggunaan sumber yang tidak cekap.
  7. Pertimbangkan untuk menggunakan partition:
    • Jika anda bekerja dengan jadual yang sangat besar, pertimbangkan untuk menggunakan partition untuk memecahkan data kepada bahagian yang lebih kecil dan lebih mudah diurus.
    • Partition boleh meningkatkan prestasi dengan membenarkan MySQL mengakses dan memproses hanya partition yang berkaitan dengan pertanyaan tertentu.
  Python dan Pangkalan Data: Panduan Pemula Terbaik

Mempunyai gabungan dengan JOIN

  1. Dapatkan pelanggan yang telah membuat pembelian dalam semua kategori produk:
SELECT 
    c.id_cliente,
    c.nombre,
    COUNT(DISTINCT v.categoria) AS total_categorias
FROM clientes c
JOIN ventas v ON c.id_cliente = v.id_cliente
GROUP BY c.id_cliente, c.nombre
HAVING COUNT(DISTINCT v.categoria) = (
    SELECT COUNT(DISTINCT categoria) FROM productos
);
  1. Paparkan pasangan produk yang telah dijual bersama dalam sekurang-kurangnya 10 pesanan:
SELECT 
    v1.id_producto AS producto1,
    v2.id_producto AS producto2,
    COUNT(*) AS total_ordenes
FROM ventas v1
JOIN ventas v2 ON v1.id_orden = v2.id_orden AND v1.id_producto < v2.id_producto
GROUP BY v1.id_producto, v2.id_producto
HAVING COUNT(*) >= 10;
  1. Dapatkan kategori produk dengan jumlah jualan lebih tinggi daripada purata jualan semua kategori, dengan mengambil kira hanya jualan dari 6 bulan lalu:
SELECT 
    p.categoria,
    SUM(v.total) AS total_ventas
FROM productos p
JOIN ventas v ON p.id_producto = v.id_producto
WHERE v.fecha >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
GROUP BY p.categoria
HAVING SUM(v.total) > (
    SELECT AVG(total_ventas)
    FROM (
        SELECT p.categoria, SUM(v.total) AS total_ventas
        FROM productos p
        JOIN ventas v ON p.id_producto = v.id_producto
        WHERE v.fecha >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
        GROUP BY p.categoria
    ) AS subconsulta
);

Kesilapan biasa semasa menggunakan Having dan cara mengelakkannya

  1. Menggunakan lajur bukan agregat dalam klausa Mempunyai tanpa memasukkannya dalam GROUP BY:
    • Ralat: Jika anda cuba merujuk lajur bukan agregat dalam klausa Mempunyai tanpa memasukkannya dalam klausa KUMPULAN OLEH, anda akan menerima ralat.
    • Penyelesaian: Pastikan anda memasukkan semua lajur bukan agregat yang disebut dalam klausa Mempunyai dalam klausa GROUP BY.
  2. Mengelirukan DI MANA dan Mempunyai syarat:
    • Ralat: Meletakkan syarat penapis dalam klausa Having yang sepatutnya berada dalam klausa WHERE, atau sebaliknya.
    • Penyelesaian: Ingat bahawa klausa WHERE digunakan sebelum mengumpulkan dan digunakan untuk menapis baris individu, manakala klausa Having digunakan selepas mengumpulkan dan digunakan untuk menapis kumpulan baris.
  3. Terlupa memasukkan klausa GROUP BY:
    • Ralat: Jika anda menggunakan fungsi agregat dalam pertanyaan anda tanpa menyatakan klausa GROUP BY, anda akan menerima ralat.
    • Penyelesaian: Pastikan anda memasukkan klausa GROUP BY dan tentukan lajur yang anda ingin kumpulkan hasil.
  4. Menggunakan fungsi agregat dalam klausa WHERE:
    • Ralat: Fungsi agregat seperti SUM, COUNT, AVG, MAX, MIN, dsb., tidak boleh digunakan secara langsung dalam klausa WHERE.
    • Penyelesaian: Jika anda perlu menapis hasil berdasarkan hasil fungsi agregat, gunakan subkueri atau alihkan syarat ke klausa Mempunyai.
  5. Tidak mengendalikan nilai nol dengan betul:
    • Pepijat: Fungsi agregat merawat nilai nol secara berbeza, yang boleh membawa kepada hasil yang tidak dijangka jika tidak dikendalikan dengan betul.
    • Penyelesaian: Gunakan fungsi seperti COUNT(*) dan bukannya COUNT(lajur) jika anda ingin memasukkan baris dengan nilai nol dalam kiraan. Pertimbangkan untuk menggunakan fungsi seperti COALESCE atau IFNULL untuk mengendalikan nilai nol dengan sewajarnya.
  6. Rprestasi yang lemah kerana indeks yang hilang atau pertanyaan yang kurang dioptimumkan:
  • Ralat: Pertanyaan menggunakan Having boleh menjadi perlahan jika indeks yang sesuai tidak digunakan atau jika pengiraan yang tidak perlu dilakukan.
  • Penyelesaian: Pastikan anda mempunyai indeks pada lajur yang digunakan dalam klausa GROUP BY dan pada lajur yang terlibat dalam syarat dalam klausa Mempunyai. Optimumkan pertanyaan dengan mengelakkan pengiraan yang tidak perlu dan menggunakan subkueri atau jadual sementara apabila sesuai.
  1. Tidak mengambil kira susunan klausa:
    • Ralat: Meletakkan klausa dalam susunan yang salah boleh mengakibatkan ralat sintaks atau hasil yang tidak dijangka.
    • Penyelesaian: Pastikan anda mengikut susunan klausa yang betul: SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY.
  2. Menggunakan syarat yang samar-samar atau tidak jelas dalam klausa Mempunyai:
    • Kesilapan: Menulis syarat yang rumit atau tidak jelas dalam klausa Having boleh menjadikan kod anda sukar difahami dan dikekalkan.
    • Penyelesaian: Tulis syarat yang jelas dan padat dalam klausa Mempunyai. Jika keadaan terlalu rumit, pertimbangkan untuk memecahkan pertanyaan kepada berbilang pertanyaan yang lebih mudah atau menggunakan subkueri untuk meningkatkan kebolehbacaan.
  3. Tidak menguji pertanyaan secara menyeluruh dengan set data yang berbeza:
    • Ralat: Pertanyaan menggunakan Having mungkin berfungsi dengan betul dengan set data ujian tetapi gagal atau menghasilkan keputusan yang salah dengan data sebenar atau lebih besar.
    • Penyelesaian: Uji pertanyaan dengan teliti dengan set data yang berbeza, termasuk kes tepi dan senario data batal atau tiada. Gunakan alat penyahpepijat dan analisis prestasi untuk mengenal pasti dan menyelesaikan masalah.
  4. Tidak mendokumentasikan pertanyaan kompleks dengan betul:
    • Pepijat: Kekurangan dokumentasi atau ulasan tentang pertanyaan rumit dengan Having boleh menyukarkan untuk difahami dan diselenggara oleh pembangun lain atau anda sendiri pada masa hadapan.
    • Penyelesaian: Tambahkan ulasan yang jelas dan ringkas yang menerangkan tujuan setiap bahagian pertanyaan, terutamanya dalam syarat klausa Mempunyai. Dokumentasikan sebarang logik kompleks atau keperluan perniagaan khusus.

Alternatif untuk Memiliki dalam kes tertentu

  1. Subqueries:
    • Daripada menggunakan Having untuk menapis hasil terkumpul, anda boleh gunakan subqueries untuk melakukan pengiraan dan penapisan yang diperlukan sebelum mengumpulkan.
    • Subkueri boleh berguna terutamanya apabila anda perlu membandingkan nilai agregat dengan nilai yang dikira dalam pertanyaan berasingan.
    • Contoh:
       SELECT *
      FROM (
          SELECT categoria, SUM(total) AS total_ventas
          FROM ventas
          GROUP BY categoria
      ) AS subconsulta
      WHERE total_ventas > 10000;
      
  2. Pandangan:
    • Jika anda mempunyai pertanyaan kompleks dengan Having yang kerap digunakan, anda boleh membuat a lihat dalam MySQL yang merangkumi logik pertanyaan.
    • Paparan menyediakan cara untuk memudahkan dan menggunakan semula pertanyaan yang kompleks, dan boleh meningkatkan kebolehbacaan dan kebolehselenggaraan kod.
    • Contoh:
       CREATE VIEW ventas_por_categoria AS
      CREATE VIEW ventas_por_categoria AS
      SELECT categoria, SUM(total) AS total_ventas
      FROM ventas
      GROUP BY categoria;
      
      SELECT *
      FROM ventas_por_categoria
      WHERE total_ventas > 10000;
      
  3. Jadual terbitan:
    • Sama seperti subkueri, jadual terbitan membolehkan anda melakukan pengiraan dan penapisan dalam pertanyaan dalaman dan kemudian menggunakan keputusan dalam pertanyaan utama.
    • Jadual terbitan boleh berguna apabila anda perlu melakukan berbilang pengagregatan atau penapisan kompleks sebelum menggabungkan hasil dengan jadual lain.
    • Contoh:
       SELECT c.nombre, v.total_ventas
      FROM clientes c
      JOIN (
          SELECT id_cliente, SUM(total) AS total_ventas
          FROM ventas
          GROUP BY id_cliente
      ) AS v ON c.id_cliente = v.id_cliente
      WHERE v.total_ventas > 1000;
      
  4. Fungsi Tetingkap:
    • Fungsi tetingkap seperti ROW_NUMBER(), RANK(), DENSE_RANK(), dsb. boleh digunakan untuk melakukan pengiraan dan penapisan berdasarkan partition data tanpa menggunakan Having.
    • Fungsi tetingkap amat berguna apabila anda perlu melakukan pengiraan berdasarkan kumpulan baris yang berkaitan dan menapis keputusan berdasarkan pengiraan tersebut.
    • Contoh:
       SELECT *
      FROM (
          SELECT categoria, total, 
                 ROW_NUMBER() OVER (PARTITION BY categoria ORDER BY total DESC) AS rn
          FROM ventas
      ) AS subconsulta
      WHERE rn <= 3;
      

Mempunyai data nol dan nilai lalai

  1. Fungsi Agregat dan Nilai Null:
    • Fungsi agregat, seperti SUM, AVG, COUNT, dsb., merawat nilai nol secara berbeza bergantung pada fungsi tertentu.
    • COUNT(*) termasuk semua baris dalam kiraan, malah baris dengan nilai nol dalam semua lajur.
    • COUNT(lajur) hanya mengira baris di mana lajur yang ditentukan tidak mempunyai nilai nol.
    • SUM dan AVG mengabaikan nilai nol dan hanya beroperasi pada nilai bukan nol.
    • Contoh:
       SELECT departamento, COUNT(*) AS total_empleados, AVG(salario) AS salario_promedio
      FROM empleados
      GROUP BY departamento
      HAVING AVG(salario) > 5000;
      
  2. Mengendalikan nilai nol dengan COALESCE atau IFNULL:
    • Jika anda mempunyai lajur yang mungkin mengandungi nilai nol dan anda ingin memasukkannya dalam Mempunyai pengiraan atau syarat, anda boleh menggunakan fungsi COALESCE atau IFNULL untuk memberikan nilai lalai.
    • COALESCE(column, default_value) mengembalikan nilai bukan nol pertama dalam senarai argumen.
    • IFNULL(column, default_value) mengembalikan nilai lalai yang ditentukan jika lajur adalah batal.
    • Contoh:
       SELECT departamento, AVG(COALESCE(salario, 0)) AS salario_promedio
      FROM empleados
      GROUP BY departamento
      HAVING AVG(COALESCE(salario, 0)) > 5000;
      
  3. Menapis kumpulan dengan nilai nol:
    • Jika anda ingin menapis kumpulan berdasarkan kehadiran atau ketiadaan nilai nol dalam lajur tertentu, anda boleh menggunakan syarat IS NULL atau IS NOT NULL dalam klausa Having.
    • Contoh:
       SELECT departamento, COUNT(*) AS total_empleados
      FROM empleados
      GROUP BY departamento
      HAVING MAX(salario) IS NULL;
      
  4. Nilai lalai dalam Mempunyai syarat:
    • Apabila membandingkan hasil fungsi agregat dengan nilai lalai dalam klausa Mempunyai, berhati-hati dengan logik keadaan.
    • Pastikan nilai lalai yang digunakan adalah konsisten dengan logik keadaan dan memberikan hasil yang diharapkan.
    • Contoh:
       SELECT departamento, AVG(COALESCE(salario, 0)) AS salario_promedio
      FROM empleados
      GROUP BY departamento
      HAVING AVG(COALESCE(salario, 0)) > 0;
      
  5. Pertimbangan prestasi dengan nilai nol:
    • Mengendalikan nilai nol dalam fungsi agregat dan Mempunyai syarat boleh menjejaskan prestasi pertanyaan, terutamanya pada set data yang besar.
    • Jika anda mempunyai sejumlah besar nilai nol dalam lajur yang digunakan dalam fungsi agregat, pertimbangkan untuk menggunakan indeks separa atau strategi pra-penapisan untuk meningkatkan prestasi.
    • Contoh:
       CREATE INDEX idx_empleados_salario ON empleados (salario) WHERE salario IS NOT NULL;
      

Amalan baik apabila menggunakan Having

  1. Gunakan nama lajur deskriptif dan alias:
    • Berikan nama deskriptif kepada lajur dan alias dalam klausa SELECT untuk meningkatkan kebolehbacaan pertanyaan.
    • Gunakan nama yang jelas menggambarkan tujuan atau kandungan setiap lajur atau ungkapan.
    • Contoh:
       SELECT departamento, COUNT(*) AS total_empleados, AVG(salario) AS salario_promedio
      FROM empleados
      GROUP BY departamento
      HAVING AVG(salario) > 5000;
      
  2. Tulis syarat yang jelas dan ringkas:
    • Tulis syarat yang jelas dan ringkas dalam klausa Having untuk menjadikan kod anda lebih mudah difahami dan diselenggara.
    • Elakkan keadaan yang terlalu rumit atau bersarang, dan pertimbangkan untuk memecahkan pertanyaan kepada bahagian yang lebih kecil dan lebih mudah diurus jika perlu.
    • Contoh:
       HAVING COUNT(DISTINCT categoria) > 3 AND SUM(total_ventas) > 10000;
      
  3. Gunakan fungsi agregat yang sesuai:
    • Pilih fungsi agregat yang sesuai berdasarkan keperluan anda dan jenis data lajur.
    • Gunakan COUNT(*) untuk mengira semua baris, termasuk yang mempunyai nilai nol.
    • Menggunakan COUNT(lajur) untuk mengira baris yang lajur yang ditentukan tidak mempunyai nilai nol.
    • Gunakan SUM, AVG, MAX dan MIN mengikut kesesuaian untuk melaksanakan pengiraan agregat.
    • Contoh:
       HAVING COUNT(*) > 100 AND AVG(precio) < 50;
      
  4. Gunakan penapis dalam klausa WHERE apabila boleh:
    • Jika anda boleh menapis baris individu sebelum mengumpulkan menggunakan klausa WHERE, berbuat demikian untuk mengurangkan jumlah data yang diproses dalam klausa Memiliki.
    • Menapis baris sebelum mengumpulkan boleh meningkatkan prestasi pertanyaan.
    • Contoh:
       SELECT categoria, SUM(total_ventas) AS total_ventas
      FROM ventas
      WHERE fecha >= '2023-01-01' AND fecha < '2024-01-01'
      GROUP BY categoria
      HAVING SUM(total_ventas) > 10000;
      
  5. Gunakan subkueri atau jadual terbitan apabila perlu:
    • Jika anda perlu melakukan pengiraan atau penapis yang rumit berdasarkan hasil agregat, pertimbangkan untuk menggunakan subkueri atau jadual terbitan.
    • Subkueri dan jadual terbitan boleh meningkatkan kebolehbacaan dan prestasi dalam pertanyaan kompleks.
    • Contoh:
       SELECT *
      FROM (
          SELECT categoria, SUM(total_ventas) AS total_ventas
          FROM ventas
          GROUP BY categoria
      ) AS subconsulta
      WHERE total_ventas > (SELECT AVG(total_ventas) FROM ventas);
      
  6. Dokumen dan ulas kod anda:
    • Tambahkan ulasan yang jelas dan ringkas untuk menerangkan tujuan dan logik bahagian berlainan pertanyaan anda, terutamanya dalam klausa Having.
    • Dokumentasi yang betul memudahkan pembangun lain dan anda sendiri memahami dan mengekalkan kod anda pada masa hadapan.
    • Contoh:
       -- Obtener las categorías con un total de ventas superior al promedio
      SELECT categoria, SUM(total_ventas) AS total_ventas
      FROM ventas
      GROUP BY categoria
      HAVING SUM(total_ventas) > (SELECT AVG(total_ventas) FROM ventas);
      
  7. Jalankan ujian yang meluas:
    • Uji pertanyaan anda dengan Mempunyai menggunakan set data dan kes ujian yang berbeza.
    • Sahkan bahawa keputusan yang diperoleh adalah seperti yang dijangkakan dan bahawa pertanyaan itu berfungsi dengan betul dalam senario yang berbeza, termasuk kes tepi dan data nol.
    • Gunakan alat penyahpepijat dan analisis prestasi untuk mengenal pasti dan menyelesaikan masalah.
    • Contoh:
       -- Prueba con diferentes umbrales de total de ventas
      HAVING SUM(total_ventas) > 10000;
      HAVING SUM(total_ventas) > 50000;
      HAVING SUM(total_ventas) > 100000;
      
  8. Pertimbangkan prestasi dan pengoptimuman:
    • Ingat prestasi semasa menulis pertanyaan menggunakan Having, terutamanya pada set data yang besar.
    • Gunakan indeks yang sesuai pada lajur yang digunakan dalam klausa GROUP BY dan Mempunyai syarat untuk meningkatkan kelajuan pertanyaan.
    • Elakkan pengiraan yang tidak perlu atau berlebihan dalam klausa Mempunyai.
    • Contoh:
       -- Utiliza índices en las columnas de agrupación y filtrado
      CREATE INDEX idx_ventas_categoria ON ventas (categoria);
      CREATE INDEX idx_ventas_fecha ON ventas (fecha);
      
  9. Mengekalkan konsistensi dan penyeragaman:
    • Ikuti konvensyen penamaan dan pemformatan yang konsisten dalam semua pertanyaan anda dengan Having.
    • Gunakan gaya pengekodan yang konsisten, seperti menggunakan huruf besar kata kunci dan lekukan yang betul.
    • Mengekalkan konsistensi dalam struktur pertanyaan dan susunan klausa.
    • Contoh:
       SELECT categoria, SUM(total_ventas) AS total_ventas
      FROM ventas
      WHERE fecha >= '2023-01-01' AND fecha < '2024-01-01'
      GROUP BY categoria
      HAVING SUM(total_ventas) > 10000
      ORDER BY total_ventas DESC;
      
  10. Kekal dikemas kini dan belajar daripada komuniti:
    • Ikuti perkembangan terkini dengan ciri MySQL baharu dan peningkatan yang berkaitan dengan prestasi dan pengoptimuman pertanyaan.
    • Belajar daripada komuniti pembangun dan kongsi pengetahuan dan pengalaman anda.
    • Sertai forum, blog dan persidangan untuk mempelajari amalan terbaik dan mengikuti perkembangan terkini.
    • Contoh:
    • Ikuti blog dan sumber dalam talian tentang pertanyaan.
    • Mengambil bahagian dalam komuniti pembangun dan bertanya soalan dalam forum khusus.
    • Menghadiri persidangan dan webinar pada MySQL dan pangkalan data.
  11. Mempunyai pertanyaan dengan penomboran dan pengisihan

    1. Penomboran dengan LIMIT dan OFFSET:
      • Penomboran membolehkan anda membahagikan hasil pertanyaan kepada halaman yang lebih kecil dan lebih mudah diurus.
      • Gunakan klausa LIMIT untuk menentukan bilangan maksimum baris untuk dikembalikan dan klausa OFFSET untuk menentukan bilangan baris untuk dilangkau sebelum mula mengembalikan hasil.
      • Contoh:
         SELECT categoria, SUM(total_ventas) AS total_ventas
        FROM ventas
        GROUP BY categoria
        HAVING SUM(total_ventas) > 10000
        ORDER BY total_ventas DESC
        LIMIT 10 OFFSET 0;
        
    2. Mengisih dengan ORDER BY:
      • Klausa ORDER BY digunakan untuk menyusun keputusan pertanyaan mengikut satu atau lebih lajur.
      • Anda boleh mengisih keputusan dalam tertib menaik (ASC) atau menurun (DESC).
      • Contoh:
         SELECT categoria, SUM(total_ventas) AS total_ventas
        FROM ventas
        GROUP BY categoria
        HAVING SUM(total_ventas) > 10000
        ORDER BY total_ventas DESC;
        
    3. Interaksi antara Mempunyai, ORDER BY dan Had:
      • Adalah penting untuk ambil perhatian susunan klausa Having, ORDER BY dan LIMIT digunakan.
      • Klausa Having pertama kali digunakan untuk menapis kumpulan baris yang memenuhi syarat yang ditentukan.
      • Klausa ORDER BY kemudian digunakan untuk mengisih hasil yang ditapis.
      • Akhir sekali, klausa LIMIT dan OFFSET digunakan untuk mengehadkan bilangan baris yang dikembalikan dan menomborkan hasil.
      • Contoh:
         SELECT categoria, SUM(total_ventas) AS total_ventas
        FROM ventas
        GROUP BY categoria
        HAVING SUM(total_ventas) > 10000
        ORDER BY total_ventas DESC
        LIMIT 10 OFFSET 20;
        
    4. Pertimbangan Prestasi:
      • Apabila bekerja dengan set data yang besar dan menggunakan penomboran dan pengisihan bersama-sama dengan Having, adalah penting untuk mempertimbangkan prestasi pertanyaan.
      • Pastikan anda mempunyai indeks yang betul pada lajur yang digunakan dalam klausa GROUP BY, Mempunyai syarat dan lajur pengisihan untuk meningkatkan kecekapan pertanyaan.
      • Perlu diingat bahawa pelayan pangkalan data Anda mesti memproses dan mengisih semua keputusan sebelum menggunakan LIMIT dan OFFSET, yang boleh menjejaskan prestasi pada set data yang sangat besar.
      • Pertimbangkan untuk menggunakan teknik penomboran yang lebih maju, seperti penomboran berasaskan kursor atau penomboran menggunakan kekunci utama, untuk meningkatkan prestasi dalam kes tertentu.
    5. Penomboran dan pengisihan dalam aplikasi:
      • Apabila membangunkan aplikasi yang memerlukan penomboran dan pengisihan bersama-sama dengan Having, adalah penting untuk mereka bentuk strategi yang sesuai untuk mengendalikan aspek ini dengan cekap.
      • Gunakan parameter dalam pertanyaan anda untuk membenarkan penomboran dinamik dan pengisihan berdasarkan pilihan pengguna.
      • Pertimbangkan caching hasil penomboran dan diisih untuk mengelakkan pertanyaan berulang dan meningkatkan prestasi.
      • Contoh:
         SELECT categoria, SUM(total_ventas) AS total_ventas
        FROM ventas
        GROUP BY categoria
        HAVING SUM(total_ventas) > ? 
        ORDER BY ? ?
        LIMIT ? OFFSET ?;
        

    Lanjutan Menggunakan Having dengan Subqueries

    1. Tapis kumpulan berdasarkan hasil subkueri agregat:
      • Anda boleh menggunakan subkueri dalam klausa Mempunyai untuk menapis kumpulan berdasarkan hasil agregat pertanyaan lain.
      • Ini berguna apabila anda perlu membandingkan nilai agregat setiap kumpulan dengan nilai yang dikira dalam subkueri.
      • Contoh:
         SELECT categoria, SUM(total_ventas) AS total_ventas
        FROM ventas
        GROUP BY categoria
        HAVING SUM(total_ventas) > (
            SELECT AVG(total_ventas)
            FROM (
                SELECT categoria, SUM(total_ventas) AS total_ventas
                FROM ventas
                GROUP BY categoria
            ) AS subconsulta
        );
        
    2. Tapis kumpulan berdasarkan kewujudan baris dalam subkueri:
      • Anda boleh menggunakan klausa EXISTS dalam kombinasi dengan Perlu menapis kumpulan berdasarkan kewujudan baris dalam subkueri yang berkaitan.
      • Ini berguna apabila anda ingin menyimpan hanya kumpulan yang mempunyai hubungan khusus dengan hasil subkueri.
      • Contoh:
         SELECT categoria, SUM(total_ventas) AS total_ventas
        FROM ventas
        GROUP BY categoria
        HAVING EXISTS (
            SELECT 1
            FROM productos
            WHERE productos.categoria = ventas.categoria
            AND productos.precio > 100
        );
        
    3. Tapis kumpulan berdasarkan keahlian dalam set nilai:
      • Anda boleh menggunakan klausa IN dalam kombinasi dengan Perlu menapis kumpulan berdasarkan keahlian dalam satu set nilai yang diperoleh daripada subkueri.
      • Ini berguna apabila anda ingin mengekalkan hanya kumpulan yang nilai agregatnya sepadan dengan nilai yang dinyatakan dalam subkueri.
      • Contoh:
         SELECT categoria, SUM(total_ventas) AS total_ventas
        FROM ventas
        GROUP BY categoria
        HAVING categoria IN (
            SELECT categoria
            FROM productos
            WHERE precio > 100
        );
        
    4. Tapis kumpulan berdasarkan perbandingan dengan nilai minimum atau maksimum:
      • Anda boleh menggunakan subqueries dalam klausa Having untuk menapis kumpulan berdasarkan perbandingan dengan nilai minimum atau maksimum yang diperoleh daripada pertanyaan lain.
      • Ini berguna apabila anda ingin mengekalkan hanya kumpulan yang nilai agregatnya memenuhi kriteria tertentu mengenai outlier.
      • Contoh:
         SELECT categoria, SUM(total_ventas) AS total_ventas
        FROM ventas
        GROUP BY categoria
        HAVING SUM(total_ventas) > (
            SELECT MAX(total_ventas)
            FROM (
                SELECT categoria, SUM(total_ventas) AS total_ventas
                FROM ventas
                GROUP BY categoria
            ) AS subconsulta
            WHERE categoria <> ventas.categoria
        );
        

    Mengoptimumkan Having dengan indeks dan sekatan

    1. Menggunakan indeks pada mengelompokkan lajur:
      • Buat indeks pada lajur yang digunakan dalam klausa KUMPULAN OLEH untuk meningkatkan kecekapan pengelompokan.
      • Indeks membolehkan MySQL mencari dengan cepat baris yang dimiliki oleh setiap kumpulan, yang mempercepatkan proses pengumpulan.
      • Contoh:
         CREATE INDEX idx_ventas_categoria ON ventas (categoria);
        
    2. Menggunakan indeks pada lajur penapis:
      • Cipta indeks pada lajur yang digunakan dalam syarat klausa Mempunyai untuk meningkatkan kelajuan penapisan.
      • Indeks membolehkan MySQL mencari baris dengan cepat yang memenuhi syarat yang dinyatakan dalam Having.
      • Contoh:
         CREATE INDEX idx_ventas_total ON ventas (total_ventas);
        
    3. Menggunakan indeks komposit:
      • Buat indeks komposit yang merangkumi kedua-dua lajur pengumpulan dan lajur penapisan.
      • Indeks komposit boleh meningkatkan lagi prestasi dengan membenarkan MySQL melakukan carian dan penapisan yang cekap menggunakan satu indeks.
      • Contoh:
         CREATE INDEX idx_ventas_categoria_total ON ventas (categoria, total_ventas);
        
    4.  CREATE TABLE ventas (
      id INT,
      categoria VARCHAR(50),
      total_ventas DECIMAL(10,2),
      fecha DATE
      )
      PARTITION BY HASH(YEAR(fecha))
      PARTITIONS 5;
      

      Mempunyai dalam persekitaran konkurensi tinggi