SQL - VS nereye sahip


205

Aşağıdaki iki tablo var:

1. Lecturers (LectID, Fname, Lname, degree).
2. Lecturers_Specialization (LectID, Expertise).

En fazla uzmanlık alan öğretim görevlisini bulmak istiyorum. Bunu denediğimde, çalışmıyor:

SELECT
  L.LectID, 
  Fname, 
  Lname 
FROM Lecturers L, 
     Lecturers_Specialization S
WHERE L.LectID = S.LectID
AND COUNT(S.Expertise) >= ALL (SELECT
  COUNT(Expertise)
FROM Lecturers_Specialization
GROUP BY LectID);

Ama bunu denediğimde işe yarıyor:

SELECT
  L.LectID,
  Fname,
  Lname 
FROM Lecturers L,
     Lecturers_Specialization S
WHERE L.LectID = S.LectID
GROUP BY L.LectID,
         Fname,
         Lname 
HAVING COUNT(S.Expertise) >= ALL (SELECT
  COUNT(Expertise)
FROM Lecturers_Specialization
GROUP BY LectID); 

Sebebi nedir? Teşekkürler.


2
Hangi SQL sürümünü kullandığınızı netleştirebilir misiniz (MySQL, MS SQL, PostgreSQL, Oracle, vb.). Ayrıca, "çalışmıyor" derken, sonuçların beklediğiniz gibi olmadığı veya derleme / ayrıştırma hatası olduğu anlamına mı geliyor?
jklemmack

2
Neden MAX yerine TÜMÜ kullanıyorsunuz? Bir avantajı var mı?
skan

Yanıtlar:


354

WHEREfıkra, münferit satırlara bir koşul getirir ; HAVINGcümlesi toplamalar üzerinde bir koşulu , yani sayım, ortalama, min, maks veya toplam gibi tek bir sonucun birden çok satırdan üretildiği seçim sonuçları ile ilgili bir koşul getirmektedir . Sorgunuz ikinci tür bir koşulu (yani bir toplamadaki bir koşulu) gerektirir, dolayısıyla HAVINGdoğru şekilde çalışır.

Genel bir kural olarak, WHEREönce GROUP BYve HAVINGsonra kullanın GROUP BY. Bu oldukça ilkel bir kuraldır, ancak vakaların% 90'ından fazlasında yararlıdır.

Siz oradayken, birleştirmenin ANSI sürümünü kullanarak sorgunuzu yeniden yazmak isteyebilirsiniz:

SELECT  L.LectID, Fname, Lname
FROM Lecturers L
JOIN Lecturers_Specialization S ON L.LectID=S.LectID
GROUP BY L.LectID, Fname, Lname
HAVING COUNT(S.Expertise)>=ALL
(SELECT COUNT(Expertise) FROM Lecturers_Specialization GROUP BY LectID)

Bu teta birleştirme koşuluWHERE olarak kullanılan ortadan kaldıracaktı .


40

HAVINGagregalarda faaliyet göstermektedir. Yana COUNTbir toplama işlevi olan, bir de kullanamazsınız WHEREmaddesinin.

İşte toplama işlevleri üzerinde MSDN'den bazı okuma.


30

İlk olarak Cümlelerin yerine getirilme sırasını bilmeliyiz, yani FROM> NEREDE> GRUPLA> HAVING> DISTINCT> SELECT> ORDER BY. Yana NEREDE Madde önce işletilirse GRUBU TARAFINDAN Madde kayıtları uygulayarak filtrelenmiş edilemez WHERE a GRUP TARAFINDAN kayıtlarını uyguladı.

"HAVING, WHERE yan tümcesi ile aynıdır, ancak gruplandırılmış kayıtlara uygulanır".

ilk olarak WHERE deyimi, koşula göre kayıtları getirir, ardından GROUP BY deyimi bunları uygun şekilde gruplandırır ve sonra HAVING deyimi, sahip koşula bağlı olarak grup kayıtlarını getirir.


Bu işlem sırası her zaman kullanılıyor mu? Sorgu iyileştirici siparişi değiştirirse ne olur?
MSIS

1
@ MSIS, sorgu iyileştiricisi siparişi değiştirse bile, sonuç bu siparişin takip edildiği gibi olmalıdır . Bu mantıklı bir düzen.
Stephen

18
  1. WHERE deyimi SELECT, INSERT ve UPDATE deyimleriyle kullanılabilirken HAVING yalnızca SELECT deyimi ile kullanılabilir.

  2. Toplama işleminden önce satırları NEREDE filtreler (GRUP BY), toplanmalardan sonra HAVALANDIRMA grup grupları.

  3. Toplama işlevi HAVING yan tümcesinde yer alan bir alt sorguda olmadığı sürece WHERE yan tümcesinde kullanılamaz; oysa HAVING yan tümcesinde toplu işlevler kullanılabilir.

Kaynak


11

Bir sorguda her ikisinin bir örneğini görmedim. Yani bu örnek yardımcı olabilir.

  /**
INTERNATIONAL_ORDERS - table of orders by company by location by day
companyId, country, city, total, date
**/

SELECT country, city, sum(total) totalCityOrders 
FROM INTERNATIONAL_ORDERS with (nolock)
WHERE companyId = 884501253109
GROUP BY country, city
HAVING country = 'MX'
ORDER BY sum(total) DESC

Bu, tabloyu önce companyId tarafından filtreler, ardından (ülkeye ve şehre göre) gruplandırır ve ayrıca yalnızca Meksika'nın şehir şehirlerine göre filtreler. Toplamada şirket kimliği gerekli değildi, ancak GROUP BY'ı kullanmadan önce sadece istediğimiz satırları filtrelemek için NEREDEN'i kullanabildik.


dönüştürebileceğiniz gibi iyi bir örnek değil: `` NEREDE şirket kimliği = 884501253109 Ülke bazında GRUP, ülke HAVING = 'MX' `için:` NEREDE şirket kimliği = 884501253109, ülke = 'MX' GRUP
ŞEHİR

[Ülke] filtrelemesini yalnızca NEREYE taşıdığınızda, [ülke] artık GROUP BY topluluğuna dahil olmadığından, sorgu SELECT [ülke] 'den hata verir. Bu nedenle seçilemez.
Nhan

Optimizasyon noktanız [ülke] 'nin NEREYE taşınmasıyla ilgilidir, çünkü daha sonra GROUP BY olarak ayarlanmış daha küçük bir veri olur. Tabii ki bu sadece olası kullanımları gösteren bir örnektir. HAVING toplamı (toplam)> 1000 olarak değiştirebiliriz ve bu, NEREDE ve HAVING'i dahil etmek için tamamen geçerli bir durum olacaktır.
Nhan

9

Toplama işlevleriyle where yan tümcesini kullanamazsınız, çünkü koşul bazında getirme kayıtları, kayıt ile tablo kaydına girer ve daha sonra verdiğimiz koşul temelinde kayıt getirilir. Yani o zaman nerede cümle yapamayız. Clause sahip sonuç bir sorgu çalıştırdıktan sonra aldığımız sonuçSet üzerinde çalışır.

Örnek sorgu:

select empName, sum(Bonus) 
from employees 
order by empName 
having sum(Bonus) > 5000;

Bu, sonuç kümesini geçici bir bellekte saklar, ardından yan tümce sahip olmak çalışmasını gerçekleştirir. Böylece burada toplu işlevleri kolayca kullanabiliriz.


2
Bence HAVING yan tümcesini GROUP BY yan tümcesi olmadan kullanamayız. HAVING Clause - SELECT -> FROM -> NEREDE -> GROUP BY -> HAVING -> SİPARİŞ VER
Morez

4

1. Biz WHERE yan tümcesi ile değil HAVING yan tümcesi ile toplama işlevi kullanabilirsiniz min, max, avg.

2. NEREDE yan tümcesi tuple ile kayıt grubunu ortadan kaldırır HAVING yan tümcesi grup grubundan tüm grubu kaldırır

Çoğunlukla HAVING, veri gruplarınız olduğunda ve WHERE ise satırlardaki verileriniz olduğunda kullanılır.

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.