简体   繁体   中英

Selecting only such groups that contain certain value

First of all, even though this SQL: How do you select only groups that do not contain a certain value? thread is almost identical to my problem, it doesn't fully dissipate my confusion about the problem.

Let's have a table "Contacts" like this one:

+----------------------+
| Department FirstName |
+----------------------+
| 100 Thomas           |
| 200 Peter            |
| 100 Jerry            |
+----------------------+

First, I want to group the rows by the department number and show number of rows in each displayed group. This, I believe, can be easily done by the following query.

SELECT Department, Count(*) As "Rows_in_group"
FROM Contacts
GROUP BY Department

This outputs 2 groups. First with dep.no. 100 containing 2 rows, second with 200 containing only one row.

, I want to extend the query to exclude any group that doesn't contain certain value in certain column (eg Thomas in FirstName). ,我想扩展查询以排除某些在某些列中不包含某些值的组(例如,FirstName中的Thomas)。 Here are my questions:

1) Reading the above-mentioned thread I was able to come up with this, which seems to work correctly:

SELECT Department, Count(*) As "Rows_in_group"
FROM Contacts
WHERE Department IN (SELECT Department FROM Contacts WHERE FirstName = "Thomas")
GROUP BY Department

I understand the "WHERE Department IN" part, but then I'd expect a value, but instead another nested query is included, which to me doesn't make much sense as I'm only beginner with SQL.

2) By accident I was able to come up with another query that also seems to work, but feels weird and I also don't understand its workings.

SELECT Department, Count(*) As "Rows_in_group"
FROM Contacts
GROUP BY Department
HAVING NOT SUM(FirstName = "Thomas") = 0

3)

I expected, that simple "HAVING FirstName='Thomas'" after the GROUP BY would do the trick as it seems to follow a common language, but it does not.

I want the whole groups to be chosen by the query so "WHERE FirstName='Thomas'" isn't s solution for my problem as it excludes all the rows that don't satisfy the condition before the grouping takes place (at least the way I understand it). 我希望通过查询选择整个组,因此“ WHERE FirstName ='Thomas'”不是解决我的问题的方法,因为它排除了在分组发生之前所有不满足条件的行(在至少是我的理解方式)。

Q: How does this work? I understand the "WHERE Department IN" part, but then I'd expect a value, but instead another nested query is included, which to me doesn't make much sense as I'm only beginner with SQL.

The nested query returns values which are used to match against Department

2) By accident I was able to come up with another query that also seems to work, but feels weird and I also don't understand its workings.

 HAVING NOT SUM(FirstName = "Thomas") = 0

"Feels weird" because, well, it is. This is not a place for the SUM function.

EDIT: Why does this work? The expression FirstName = "Thomas" gets evaluated as true or false (known as a Boolean expression). True numerically is equal to 1 and False converts to 0 (zero). By including SUM you then calculated the totals so really zero (still) means false and "not zero" is true. Then to make it weird(er) you included NOT which negated the whole thing and it becomes NOT TRUE = 0 or FALSE = FALSE (which is of course... TRUE)!!

EDIT : I think what could be more helpful to you is consideration of when to use WHERE and when to use HAVING (instead of the Boolean magic taking place). From this answer :

WHERE clause introduces a condition on individual rows ; HAVING clause introduces a condition on aggregations , ie results of selection where a single result, such as count, average, min, max, or sum, has been produced from multiple rows.

WHERE was appropriate for your example because first you want to "only return rows WHERE Department IN (100) " and then you want to "group those rows by Department " and get a COUNT of how many rows had been selected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM