HAVING ve WHERE arasındaki fark nedir?


261

Yanlış şekilde googling yapmalıyım veya zaman içinde aptalca bir an yaşıyorum.

Arasındaki fark nedir HAVINGve WHEREbir in SQL SELECTdeyimi?

DÜZENLEME: Steven'ın cevabını, bağlantıdaki önemli bilgileri içerdiği için doğru olarak işaretledim:

Ne zaman GROUP BYkullanılmaz, HAVINGdavranacağını bir gibi WHEREmaddesini

İçinde gördüğüm durum WHEREyoktu GROUP BYve karışıklığımın başladığı yer. Elbette, bunu öğrenene kadar soruda belirtemezsiniz.


44
Alıntı yaptığınız satır hiç de önemli değil. Anahtar dili, wcm belirttiği gibi , yani HAVING, oysa bir post-agregasyon filtre WHEREbir ön çekiş filtredir.
Nick Chammas

Bu bağlantı aşağıdaki tüm yorumlardan daha iyi anlamama yardımcı oldu, bazılarının bu koddan
Lijin Durairaj

Yanıtlar:


94

HAVING, SELECT deyiminde kullanılan bir grup veya bir toplama işlevi için bir arama koşulu belirtir.

Kaynak


369

HAVING: Toplama gerçekleştikten sonra koşulları kontrol etmek için kullanılır .
NEREDE: Toplama gerçekleşmeden önce koşulları kontrol etmek için kullanılır .

Bu kod:

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City

MA'daki tüm şehirlerin bir tablosunu ve her bir şehirdeki adres sayısını verir.

Bu kod:

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City
Having Count(1)>5

MA'da 5'ten fazla adres ve her şehirdeki adres sayısı ile bir şehir tablosu sunar.


7
Bu kabul edilen cevap olmalı. "Sahip olmak" ve "nerede" arasındaki ayrım bunu açıkça ortaya koymaktadır.
Paul

27

Benim için bir numaralı fark: HAVINGSQL dilinden kaldırılmışsa, hayat daha önce olduğu gibi az çok devam ederdi. Kuşkusuz, bir azınlık sorgularının türetilmiş bir tablo, CTE, vb. Kullanılarak yeniden yazılması gerekir, ancak sonuç olarak anlaşılması ve sürdürülmesi muhtemelen daha kolay olacaktır. Belki de satıcıların optimizasyon kodunun bu durumu göz önünde bulundurarak yeniden yazılması gerekebilir, bu da yine sektördeki iyileştirme fırsatıdır.

Şimdi bir an WHEREdilden çıkarmayı düşünün . Bu kez var olan sorguların çoğunun bariz bir alternatif yapı olmadan yeniden yazılması gerekecektir. Kodlayıcılar , bir önceki maddeyi simüle etmek için yan tümcesi DUALkullanarak tam olarak bir satır (ör . Oracle'da) içerdiği bilinen bir tabloya iç birleşim yaratıcı hale getirmelidir . Bu tür yapılar inşa edilecektir; dilde bir şey eksik olduğu ve durumun daha kötü olacağı açıktır.ONWHERE

TL; DR HAVINGyarın kaybedebiliriz ve işler daha kötü, muhtemelen daha iyi olmazdı, ama aynı şey söylenemez WHERE.


Buradaki cevaplardan, birçok halk bir HAVINGcümlenin bir GROUP BYcümle olmadan kullanılabileceğini anlamıyor gibi görünüyor . Bu durumda, HAVINGyan tümce tümce tümce tümce tümce tümce uygulanır ve yan tümce yalnızca sabitlerin görünmesini gerektirir SELECT. GenellikleHAVING madde toplamları içerecektir.

Bu göründüğünden daha kullanışlıdır. Örneğin, namesütunun aşağıdaki değerlerin tümü için benzersiz olup olmadığını test etmek için bu sorguyu göz önünde bulundurun T:

SELECT 1 AS result
  FROM T
HAVING COUNT( DISTINCT name ) = COUNT( name );

Yalnızca iki olası sonuç vardır: HAVINGyan tümcesi true ise, değeri içeren tek bir satırla 1sonuç, aksi takdirde sonuç boş küme olur.


Bu, "SELECT COUNT (DISTINCT adı) = COUNT (ad) T'den" ile eşdeğer olur mu?
MSpreij

@MSpreij Bunun sizin için işe yarayıp yaramadığını bilmiyorum, ancak SQL Server 2005'te çalışmıyor ancak ilki çalışıyor
Joe

22

HAVING yan tümcesi, WHERE anahtar sözcüğü toplama işlevleriyle kullanılamadığından SQL'e eklendi.

Daha fazla bilgi için bu w3schools bağlantısına göz atın

Sözdizimi:

SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value

Bunun gibi bir sorgu:

SELECT column_name, COUNT( column_name ) AS column_name_tally
  FROM table_name
 WHERE column_name < 3
 GROUP 
    BY column_name
HAVING COUNT( column_name ) >= 3;

... türetilmiş bir tablo kullanılarak (ve bu listenin çıkarılmasıyla) yeniden yazılabilir HAVING:

SELECT column_name, column_name_tally
  FROM (
        SELECT column_name, COUNT(column_name) AS column_name_tally
          FROM table_name
         WHERE column_name < 3
         GROUP 
            BY column_name
       ) pointless_range_variable_required_here
 WHERE column_name_tally >= 3;

3
Konuyu biraz özlediniz: HAVINGtüretilmiş tablolar dile eklenmediği ve SQL olana kadar ilişkisel olarak tamamlanmadığı ve kaçınılmaz olarak HAVINGgereksiz hale geldiği için eklendi.
oneday

21

İkisi arasındaki fark GROUP BY deyimiyle ilişkilidir:

  • NEREDE GROUP BY'dan önce gelir; SQL, kayıtları gruplandırmadan önce WHERE yan tümcesini değerlendirir.

  • HAVING, GROUP BY grubundan sonra gelir; SQL HAVING'i kayıtları gruplandırdıktan sonra değerlendirir.

ifade diyagramını seç

Referanslar


GROUP BY ve HAVING'in her ikisi de isteğe bağlı olduğundan, şema her iki durumu da gösterir;
Paul Sweatte

Bu soruya cevabımdan örnek sorgu: SELECT 1 AS result FROM T HAVING...- diyagramınızda HAVINGgeçmeden ulaşamıyorum GROUP BYama mükemmel geçerli ve kullanışlı sorgum yok GROUP BY. Küçük nokta: SELECTyan tümceye değişmez değerler ekleme seçeneğiniz yoktur .
birgün

@onedaywhen beri biliyor örtülü GROUP BY hakkında, neden bahsetmedin? Bu davranışın beklediğiniz şey olup olmadığını biliyor musunuz ?
Paul Sweatte

Beni bağlamdan alıntıladığınızı düşünüyoruz. Soru, mySQL'in Standarttan belirgin sapmasıyla ilgiliydi, cevabımın son paragrafı hariç tümü Standart davranışı açıklıyor ve sonuncusu " diğer cevaplarda belirtilen örtük GROUP BY yantümcesini" anlatıyor . Diyagramınızın örtük davranışı (hepsi) tanımlamayı amaçladığını mı söylüyorsunuz? İstenen davranışı elde etmek için sadece yazmanız gereken koda sadık kalmak daha yararlı olmaz mıydı?
birgün4

... ikinci linkte hangi davranışı ifade ettiğinizi bilmiyorum. İstenen sonuç, diyagramı bahsettiğim geçerli (açık) yolu gösterecek şekilde düzeltmenizdir. Bir düşünün: diyagram tüm bir sorguyu kapsıyor, ancak soru sadece WHERE->HAVINGbölümle ilgileniyor , bu yüzden detaylara dikkat etmeyi hak ediyor. Cevabımın yanlış olduğunu düşünüyorsanız, onu düzenleyin veya yorumlarda önerilen bir düzeltme gönderin.
birgün4

12

HAVINGgibi bir toplama kullandığınızda kullanılır GROUP BY.

SELECT edc_country, COUNT(*)
FROM Ed_Centers
GROUP BY edc_country
HAVING COUNT(*) > 1
ORDER BY edc_country;

8

SQL tarafından döndürülen kümeye WHERE bir sınırlama olarak uygulanır; SQL'in yerleşik küme işlemlerini ve dizinlerini kullanır ve bu nedenle sonuç kümelerini filtrelemenin en hızlı yoludur. Mümkün olduğunca daima WHERE kullanın.

Bazı agrega filtreleri için HAVING gereklidir. Sql'nin alınmasından, birleştirilmesinden ve sonuçlarını sıralamasından SONRA sorgusunu filtreler. Bu nedenle, NEREDEN çok daha yavaştır ve bunu gerektiren durumlar dışında kaçınılmalıdır.

SQL Server, NEREDE çok daha hızlı olsa bile HAVING'i kullanmanıza izin verir. Yapma.


SQL dilinde türetilmiş tablolar için destek, "bazı toplam filtreler için HAVING gerekli" iddianızın yanlış olduğu anlamına gelir.
oneday

1
İyi bir noktaya değindin. Bu cevabı yazdığım üç yıl içinde, daha önce HAVING kullanacağım türetilmiş tabloları kullanmaya doğru göç ettim. HAVING'in hala mantıklı olan bazı kullanım durumları olup olmadığını düşünmedim. Ayrıca türetilmiş bir tablonun evrensel olarak HAVING'ten daha iyi performans gösterip göstermeyeceğini de bilmiyorum.
davidcl

7

WHERE deyimi toplama işlevleri için çalışmaz
anlamına gelir: bu bonus gibi kullanmamalısınız: tablo adı

SELECT name  
FROM bonus  
GROUP BY name  
WHERE sum(salary) > 200  

BURADA YER yan tümcesi kullanmak yerine HAVING kullanmalısınız.

GROUP BY deyimini kullanmadan HAVING deyimi WHERE deyimi olarak çalışır

SELECT name  
FROM bonus  
GROUP BY name  
HAVING sum(salary) > 200  

4

Fark s / b WHEREve HAVINGyan tümcesi:

WHEREVe HAVINGcümlecikleri arasındaki temel fark , WHEREsatır işlemleri için ve HAVINGsütun işlemleri için kullanılır.

Neden HAVINGmaddeye ihtiyacımız var ?

Bildiğimiz gibi, toplama işlevleri yalnızca sütunlarda gerçekleştirilebilir, bu nedenle toplama işlevlerini WHEREyan tümcede kullanamayız . Bu nedenle, HAVINGyan tümcede toplama işlevleri kullanıyoruz .


2

Zaman GROUP BYkullanılmaz, WHEREve HAVINGmaddeleri esas olarak denktir.

Ancak, ne zaman GROUP BYkullanılır:

  • WHEREMaddesi Sonuç filtre kayıtları için kullanılır. Filtreleme, herhangi bir gruplama yapılmadan önce yapılır.
  • HAVINGMaddesi (gruba agregasyon yapıldıktan sonra koşullarını kontrol etmek için, yani,) grubundan filtre değerleri için kullanılır.

Buradan Kaynak


sahip olmak ve nerede olması esasen eşdeğer değildir. yürütme sırasında hata verecektir. HAVING yan tümcesinde geçersizdir, çünkü bir toplu işlevde veya GROUP BY yan tümcesinde bulunmaz.
Nagendra Kumar

2

Bunu düşünmenin bir yolu, sahip yan tümcesinin nerede yan tümcesine ek bir filtre olmasıdır.

Bir WHERE deyimi, bir sonucun kayıtlarını filtreler. Filtre, herhangi bir gruplama yapılmadan önce gerçekleşir. Bir HAVING maddesi grubundan filtre değerleri için kullanılan


1

Toplama sorgusunda, (Toplama işlevinin kullanıldığı herhangi bir sorgu) Bir nerede yan tümcesinde toplanan ara sonuç kümesi oluşturulmadan önce değerlendirilir,

Sahip bir cümlesindeki tahminler, oluşturulduktan SONRA toplam sonuç kümesine uygulanır. Bu nedenle, birleştirilmiş değerler üzerindeki yüklem koşulları, Nerede yan tümcesine değil, Sahip yan tümcesine yerleştirilmeli ve neden Sahip Yan tümcesinde Seç yan tümcesinde tanımlanan takma adları kullanabileceğinizi, ancak Nerede yan tümcesinde kullanamazsınız.


1

Bir sorun vardı ve aralarında başka bir fark öğrendim WHEREve HAVING. Dizinlenmiş sütunlarda aynı şekilde çalışmaz.

WHERE my_indexed_row = 123 satırları gösterir ve diğer dizinlenmiş satırlarda otomatik olarak bir "SİPARİŞ ASC" gerçekleştirir.

HAVING my_indexed_row = 123 en eski "eklenen" satırdan en yenisine kadar her şeyi gösterir, sipariş vermez.


Bunun, kullandığınız belirli SQL sunucusunun bir uygulama kazası yerine, twain arasında tanımlanmış bir fark olduğunu nasıl anlarsınız?
JdeBP

Sadece MariaDB'de test ettim. Sanırım 8 yıl önce kullandığım SQL sunucusu farklı sonuçlar üretti.
Simmoniz

0

Gönderen burada .

SQL standardı HAVING'in yalnızca GROUP BY deyimindeki sütunlara veya toplama işlevlerinde kullanılan sütunlara başvurması gerektiğini gerektirir

veritabanı satırlarına uygulanan WHERE yantümcesinin aksine


Kaynak, "Sözdizimi SQL standardından kaldırıldığı için sütun konumlarının kullanımı kullanımdan kaldırıldı" diyor. Ne yazık ki, bu yanlış: Standarttan hiçbir şey çıkarılmıyor, bu da ironik bir şekilde HAVINGtüretilmiş tablolar tarafından 'kullanımdan kaldırıldıktan sonra hala on yıllarımız var.
gün18

Biraz bilgiçlikçi ama alıntı doğru değildir, örneğin düşünün SELECT 1 FROM T HAVING COUNT(*) >= 1;- GROUP BYyan tümcedeki sütunlara (hiçbiri yoktur) veya toplu işlevlerdeki sütunlara başvurmaz (sorgu hiç sütun içermez).
gün18

0

Bir proje üzerinde çalışırken bu da benim sorumdu. Yukarıda belirtildiği gibi, HAVING zaten bulunan sorgu sonucundaki koşulu kontrol eder. Ama NEREDE , sorgu çalışırken koşulu kontrol etmek içindir.

Bunu açıklamak için bir örnek vereyim. Bunun gibi bir veritabanı tablonuz olduğunu varsayalım.

usertable {int kullanıcı kimliği, tarih tarih alanı, int günlük gelir}

Aşağıdaki satırların tabloda olduğunu varsayalım:

1, 2011-05-20, 100

1, 2011-05-21, 50

1, 2011-05-30, 10

2, 2011-05-30, 10

2, 2011-05-20, 20

Şimdi biz almak istiyorum userids ve sum(dailyincome)kiminsum(dailyincome)>100

Eğer yazarsak:

SELECT kullanıcı kimliği, toplam (günlük gelir) KULLANILABİLİR WHERE toplamından (günlük gelir)> 100 GROUP BY kullanıcı kimliği

Bu bir hata olacaktır. Doğru sorgu:

SELECT kullanıcı kimliği, toplam (günlük gelir) usertable GROUP'TAN BY userid HAVING toplamı (günlük gelir)> 100


0

WHERE yan tümcesi, temel tablodaki değerleri karşılaştırmak için kullanılırken HAVING yan tümcesi, sorgu sonuç kümesindeki toplama işlevlerinin sonuçlarını filtrelemek için kullanılabilir. Buraya tıklayın !


0

GROUP BY kullanılmadığında, WHERE ve HAVING cümleleri esasen eşdeğerdir.

Ancak, GROUP BY kullanıldığında:

  • WHERE deyimi, bir sonuçtaki kayıtları filtrelemek için kullanılır. Filtreleme, herhangi bir gruplama yapılmadan önce yapılır.
  • HAVING yan tümcesi, bir gruptaki değerleri filtrelemek için kullanılır (yani, gruplara toplama işlemi gerçekleştirildikten sonra koşulları kontrol etmek için).

-1

Bir toplama işlevi sonuçlarına dayalı bir sorgu kısıtlamak için HAVING kullanın. EG blahblahblah grubunda SOMETHING sayısı olan (SOMETHING)> 0


-1

Sadece "nerede" konusu bir satır, "sahip olma" konusu ise bir grup olabilir. Haklı mıyım?


3
Bir cevap göndermeden önce emin olmalısınız. Bu başkaları için yanıltıcı olabilir.
pippin1289
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.