1、SQL除了能用Group By分組數據之外,SQL還允許過濾分組,規定包括那些分組,排除那些分組。例如,你可能想要列出至少有兩個訂單的所有顧客。為此,必須基於完整的分組而不是個別的行進行過濾。
基於上面的例子,我們第一時間想到的是通過使用WHERE來過濾數據,拿到我們想要的結果,但是在這個列子中WHERE不能完成任務,因為WHERE過濾指定的是行,而不是分組。事實上,WHERE沒有分組的概念。
因此,SQL提供了專門用來過濾分組的類似與WHERE子句的子句,HAVING子句,事實上,幾乎所有類型的WHERE子句都可以用HAVING來代替。唯一的差別是,WHERE過濾行數據,HAVING過濾分組數據。
如下代碼:
select * from dbo.T_Unit_Equipment
現在有一個報表系統,需要展示每個單位,擁有每台設備的數量,這個時候用WHERE很麻煩(前提是數據量比較少的情況下),下面是解決代碼:
select UnitId,EquipmentName,COUNT(*) as Equipments from dbo.T_Unit_Equipment group by UnitId,EquipmentName order by UnitId ASC
ok,完成需求!
現在,改變需求,現在需要檢索出每家單位擁有的同一種設備大於等於2的記錄,下面是解決代碼:
select UnitId,EquipmentName,COUNT(*) as Equipments from dbo.T_Unit_Equipment group by UnitId,EquipmentName HAVING COUNT(*)>=2 order by UnitId ASC
ok,完成需求!
上面的代碼通過UnitId,EquipmentName兩個字段進行分組,然后SELECT語句檢索出UnitId,EquipmentName,以及Equipments(Equipments在這里是一個計算字段,通過COUNT()函數計算出每個分組的總記錄數),然后HAVING子句告訴SELECT語句只檢索出所有分組中的總記錄數大於等於2的分組記錄。這里的COUNT(*)>=2過濾了每家單位所擁有的同一種設備小於2的分組!
2、WHERE和HAVING的差別:
(1)WHERE在數據分組前進行過濾,HAVING在數據分組之后進行過濾,這是個很重要的區別,WHERE排除的行不包括在分組中。這可能會改變計算值,從而影響HAVING子句中基於這些值的過濾掉的分組,根據這個差別,我們可以確定WHERE子句和Group By子句的位置:WHERE子句會在數據分組之前,對行數據進行過濾。
(2)HAVING與WHERE非常類似,如果不指定Group By,則大多數DBMS會同等的對待他們,不過你自己要區分這一點,使用HAVING時應該結合Group By子句,而WHERE子句用於標准的行級數據過濾
下面通過一個例子來了解HAVING子句與WHERE子句的差別
select * from dbo.T_Unit_Equipment
現在需要檢索出每家單位擁有的同一種設備大於等於2的記錄,前提是設備必須有維護人員(對應表中的Person列值不能為空),下面是解決代碼:
select UnitId,EquipmentName,COUNT(*) as Equipments from dbo.T_Unit_Equipment where Person!='' group by UnitId,EquipmentName HAVING COUNT(*)>=1 order by UnitId ASC
ok,完成需求!
where 過濾了Person=''的列值,然后Group By在對剩余的數據進行分組,之后HAVING子句進行分組過濾!