- 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.
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.
- 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;
- 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;
- 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;
- 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.
- 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;
- 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;
- 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;
- 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
- 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;
- 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;
- 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;
- 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;
- 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
);
Pengoptimuman Prestasi dengan Having dalam MySQL
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
Mempunyai gabungan dengan JOIN
- 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
);
- 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;
- 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
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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
- 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;
- 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;
- 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;
- 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
- 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;
- 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;
- 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;
- 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;
- 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
- 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;
- 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;
- 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;
- 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;
- 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);
- 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);
- 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;
- 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);
- 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;
- 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.
- 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;
- 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;
- 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;
- 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.
- 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 ?;
- 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 );
- 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 );
- 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 );
- 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 );
- 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);
- 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);
- 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);
- Gunakan tahap penebat yang sesuai:
- Pilih tahap pengasingan yang sesuai untuk transaksi anda yang melibatkan pertanyaan dengan Having.
- Tahap pengasingan menentukan cara konflik konkurensi dan konsistensi data dikendalikan.
- Contohnya, tahap pengasingan REPEATABLE READ memastikan bahawa bacaan berulang dalam transaksi mengembalikan hasil yang sama, menghalang bacaan hantu.
- Laraskan tahap pengasingan berdasarkan ketekalan dan keperluan prestasi anda.
- Menggunakan kunci baris atau meja:
- MySQL menggunakan kunci untuk mengawal akses serentak kepada data dan mencegah konflik.
- Apabila anda menjalankan pertanyaan menggunakan Having, MySQL boleh menggunakan kunci peringkat baris atau jadual untuk memastikan integriti data.
- Kunci baris membolehkan tahap konkurensi yang lebih tinggi dengan mengunci hanya baris tertentu yang terlibat dalam pertanyaan, manakala kunci jadual mengunci keseluruhan jadual.
- Pilih tahap penguncian yang sesuai berdasarkan keperluan keselarasan dan prestasi anda.
- Optimumkan pertanyaan dengan Mempunyai:
- Optimumkan pertanyaan dengan Perlu meminimumkan masa pelaksanaan dan mengurangkan sekatan.
- Gunakan indeks yang sesuai untuk mengumpulkan dan menapis lajur untuk mempercepatkan carian dan penapisan.
- Elakkan pengiraan yang tidak perlu atau berlebihan dalam klausa Mempunyai.
- Pertimbangkan untuk menggunakan pertanyaan terbahagi atau pertanyaan selari untuk mengagihkan beban kerja dan meningkatkan prestasi.
- Menggunakan urus niaga dengan sewajarnya:
- Bungkus pertanyaan dengan Mempunyai transaksi dalaman untuk mengekalkan integriti data dan mengelakkan ketidakkonsistenan.
- Gunakan penyata BEGIN, COMMIT dan ROLLBACK untuk mengawal permulaan, komit dan rollback transaksi.
- Minimumkan tempoh urus niaga untuk mengurangkan kebuntuan dan menambah baik keselarasan.
- Elakkan memegang kunci yang tidak perlu untuk jangka masa yang lama.
- Pantau dan laraskan prestasi:
- Gunakan alat pemantauan dan analisis prestasi untuk mengenal pasti kesesakan dan isu konkurensi yang berkaitan dengan pertanyaan dengan Having.
- Memantau penggunaan kunci, tamat masa kunci dan kebuntuan.
- Laraskan tetapan pelayan MySQL, seperti saiz penimbal cache, saiz sesi dan parameter sambungan, untuk mengoptimumkan prestasi dalam persekitaran konkurensi tinggi.
- Skala Secara Mendatar:
- Pertimbangkan skala mendatar anda pangkalan data menggunakan teknik pembahagian atau replikasi.
- Pembahagian membolehkan anda membahagikan jadual besar kepada bahagian yang lebih kecil dan mengagihkan beban kerja merentasi berbilang nod.
- Replikasi membolehkan anda mempunyai salinan tambahan pangkalan data pada pelayan yang berbeza, membolehkan anda mengedarkan pertanyaan baca dan meningkatkan prestasi.
- Pengenalan kepada Mempunyai Klausa dalam MySQL
- Perbezaan antara WHERE dan HAVING
- Penggunaan asas Having
- Menggabungkan Having dengan fungsi agregat
- Contoh praktikal pertanyaan dengan Having
- Mempunyai gabungan dengan JOIN
- Alternatif untuk Memiliki dalam kes tertentu
- Mempunyai data nol dan nilai lalai
- Amalan baik apabila menggunakan Having
- Mempunyai pertanyaan dengan penomboran dan pengisihan
- Lanjutan Menggunakan Having dengan Subqueries
- Mengoptimumkan Having dengan indeks dan sekatan
- Mempunyai dalam persekitaran konkurensi tinggi
Isi kandungan
Mempunyai pertanyaan dengan penomboran dan pengisihan
Lanjutan Menggunakan Having dengan Subqueries
Mengoptimumkan Having dengan indeks dan sekatan
CREATE TABLE ventas (
id INT,
categoria VARCHAR(50),
total_ventas DECIMAL(10,2),
fecha DATE
)
PARTITION BY HASH(YEAR(fecha))
PARTITIONS 5;