What count(predicate) is doing in MySQL? - mysql

I was surprised to see one of my students writing
select count(title='Staff') from titles
against MySQL employees database. Does it mean to be a nice shortcut for
select sum(case when title='Staff' then 1 else 0 end) from titles
which just fails to work in MySQL 5.6 (returning full table count)?

No, this count is not a shorthand for the sum you wrote.
COUNT(exp) counts the number of rows with a not null exp.
title='Staff' is a Boolean expression, which evaluates to true if title is 'Staff', false if it's any other value or null if it's null.
So, this query is equivalent to
select count(title) from titles
which, in turn, is equivalent to
select count(*) from titles where title is not null

No!
You can't count against an condition write into brackets. It simple return all rows from that table.
select count(title='Staff') from titles
return all rows from titles

Related

Replace null with zero in sql query

I have an sql query that could potentially return null values, in the event of this I want the query to return '0'. Here is the query
SELECT (select count(goal) from fixtures where goal='1' and fixture='$fixture') as goalCountHome
from fixtures where fixture='$fixture'LIMIT 1
Any help much appreciated!
In MySql use IFNULL() function. For MsSql use ISNULL() function.
If you are using MySql, IFNULL(<column_name>, 0) should do.
This query:
SELECT (select count(goal) from fixtures where goal='1' and fixture='$fixture') as goalCountHome
FROM fixtures
WHERE fixture = '$fixture'
LIMIT 1
cannot return NULL values. The subquery is an aggregation query with no GROUP BY, so it always returns one row. That row will contain a result from COUNT(). COUNT() itself can never return a NULL value. If there are no rows, then the value will be zero.
The outer query might return no rows but that is different from NULL values.
Of course, this query is way overcomplicated, and should simply be:
SELECT COUNT(*) as goalCountHome
FROM fixtures
WHERE fixture = ? AND -- pass this in as a parameter
goal = 1 ; -- it looks like a number so I assume it is
Note that you should be passing parameters in using proper parameters rather than munging query strings.
if you need all the rows and not the rows where goal is not null you could use count(*)
select count(*)
from fixtures
where goal=1
and fixture='$fixture'
count(goal) return the number of rows where goal is not null
count(*) return the total number rows selected
otherwise in general when you need not null values in mysql you can ifnull(your_column, value) or coalesce(your_column, value)
based on you comment seems you need sum(goal)
select sum(ifnull(goal,0))
from fixtures
where goal=1
and fixture='$fixture'

COUNTNULL() as a MySQL function. How would it operate?

I am sure it would be an aggregate function because it is going to count a collection of data.
However, how does any COUNT() function operate in MySQL to perform its respective actions?
Not 100% clear what you are looking for, but for selecting a count of null values in a column, I use something like this:
SELECT SUM(CASE WHEN columnname IS NULL THEN 1 ELSE 0 END) FROM tablename;
When the value is NULL, it is assigned the value 1 otherwise 0, then summed over whatever aggregate you need.
The COUNT(*) is an aggregate function. In the SELECT list, the expression COUNT(*) will return a count of rows. Without a GROUP BY clause, all rows will be collapsed into a single row, and the COUNT(*) aggregate will contain a non-negative integer value representing the number of rows that were collapsed... a "count" of the number of rows.
As you seem to be aware, other expressions involving the COUNT() aggregate operate a little differently, with respect to NULL values.
In the SELECT list, an expression COUNT(expr) operates exactly like COUNT(*) except for rows with values of expr that evaluate to NULL are not included in the count.
This all operates according to the specification.
As far as the non-existent COUNTNULL() function, it depends what you want that to achieve. If you wanted to get a count of the rows that had a NULL value for an expression, you could perform a conditional test, and return a non-NULL value, and use the existing COUNT aggregate, for example:
SELECT COUNT(CASE WHEN expr IS NULL THEN 1 ELSE NULL END) AS `COUNTNULL`
FROM ...
I don't remember where I learned this technique, but arguably the most elegant -- or at least minimalistic -- way to invert the logic of COUNT() is with this expression, which admittedly gives a first impression that black magic may somehow be involved... but it's perfectly legitimate:
COUNT(column1 IS NULL OR NULL)
...this correctly counts only the rows where column1 is null, because it is equivalent to the following expression...
COUNT( (column1 IS NULL) OR (NULL) )
It's a boolean expression that can only ever evaluate to 1 ("true," when column1 is null, and this row is thus counted), or NULL (otherwise, so the row will not be counted).
Logically, it's equivalent to the CASE expression offered by #spencer7593.

Why don't counts using 'LIKE' in SQL match?

I have one table ABC with EMPLID, GRADE, SALARY and DATE as its fields.
I am executing the following 3 statements:
select count(*) from ABC;
Result :- 458
select count(*) from ABC where GRADE LIKE '%def%';
Result :- 0
select count(*) from ABC where GRADE NOT LIKE '%def%';
Result :- 428
My point here is: the result of second query plus the result of third query should be equal to the result of first query, shouldn't it?
Looks like you have 30 records where the GRADE is null.
null values are unknown, so do not match either condition.
Sql uses a three-valued logic: true, false &unknown. If you compare a NULL to any other value the result is unknown. NOT(unknown) is still unknown.
A WHERE clause only returns rows that evaluate to true. So the missing 30 rows in your example have a NULL in the Grade column.
Note that apart from the obvious case where you can have NULL values in your table (as others have mentioned), you could also have empty strings.
In Oracle:
-- Returns nothing
select 1 from dual where '' like '%'
In MySQL:
-- Returns 1
select 1 from dual where '' like '%'
Since you tagged your question with both oracle and mysql, you might be running into an incompatibility here, as in oracle '' IS NULL holds true!

Query to return (grouped) rows where no row with column=condition exists

Let's say I have a table with two columns, a client_id and a boolean.
There are multiple data entries for a given client_id, each of which may or may not have the boolean value set to true.
I need a query that will return only the client_ids that have NO ROWS with the boolean set to true, and I need it grouped by client_id.
I'm sure this is simple, it just escapes me right now.
Use the HAVING clause to filter the groups:
SELECT client_id FROM my_table GROUP BY client_id HAVING SUM(boolean) = 0
Note that SUM(boolean) works in MySQL because it does not have true boolean types; in other RDBMS you would either have to use a different aggregate function or else test the boolean and return a result that can be used in SUM():
... HAVING SUM(CASE WHEN boolean THEN 1 END) = 0

MySQL COUNT() and nulls

Am I correct in saying:
COUNT(expr)
WHERE expr IS NOT *
Will count only non nulls?
Will COUNT(*) always count all rows? And What if all columns are null?
Correct. COUNT(*) is all rows in the table, COUNT(Expression) is where the expression is non-null only.
If all columns are NULL (which indicates you don't have a primary key, so this shouldn't happen in a normalized database) COUNT(*) still returns all of the rows inserted. Just don't do that.
You can think of the * symbol as meaning "in the table" and not "in any column".
This is covered in the MySQL Reference Manual.
If you want to count NULLs as well, try
SELECT COUNT(IFNULL(col, 1)) FROM table;
just checked:
select count(*)
returns 1 with one record filled with NULLs
select count(field)
returns 0.
I don't see the point in the record with NULL values. Such record must not exist.
count(*) is not for non-null columns, it's just the way to ask to count all rows. Roughly equivalent to count(1).
Using MySQL I found this simple way:
SELECT count(ifnull(col,1)) FROM table WHERE col IS NULL;
This way will not work:
SELECT count(col) FROM table WHERE col IS NULL;
If you want to count only the nulls you can also use COUNT() with IF.
Example:
select count(*) as allRows, count(if(nullableField is null, 1, NULL)) as missing from myTable;
You can change the if condiditon to count what you actually want. So you can have multiple counts in one query.
select count(*) as 'total', sum(if(columna is null, 1, 0)) as 'nulos' from tabla;