MySQL COUNT() and nulls - mysql

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;

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'

SQL Select Max of Columns Where Date is Not Null

I currently am using this query to select some data:
SELECT DISTINCT a.code AS code, name, max(scen.Is3D) AS Is3D FROM locations LEFT JOIN .... The scen table has columns Is3D and Date. I only want to select the max of items where the date IS NOT NULL. I tried max(scen.Is3D WHERE scen.Date IS NOT NULL), but that didn't work. I cannot change anything after the FROM in my query, so I need that filtering to be done in the MAX, if possible. I am using MySQL 5.7.
You can use:
MAX(CASE WHEN scen.date IS NOT NULL THEN scen.Is3D END) AS Is3D
The CASE expression returns NULL when none of the WHEN conditions is met, but MAX() ignores null values, so this will just return the max of the Is3D columns in the selected rows.
So if we can't change anything after the FROM, then we cannot get a perfect solution here. Since you are SELECTing out the NULL values. One thing that we can try if we can only modify the final output is this.
SELECT MAX(ISNULL(scen.Date,0))...
This will replace all the NULLs with 0, but it would help to know exactly what you are trying to do. Why are you so convinced that the query itself cannot be modified in any way?
The other solution would be to put the whole query in another wrapper.
That would look like:
SELECT *
FROM (
[your whole query here]
) AS inner
WHERE inner.Date IS NOT NULL

mysql substring get only characters

I have records like these:
RCV0001
RCV0002
RTN0003
RTN0004
SLE0005
RCV0006
I want to query for records that start with 'RCV' only and display only records.
This is what I've tried so far:
select substring(documentnumber, 1)
LIKE '%RCV%'
from transactionheader
But I'm not getting my desired result. Any ideas? I'd gladly appreciate your help. Thanks.
Will need to add a filter on the where statement
select documentnumber
from transactionheader
where documentnumber LIKE 'RCV%'
The expression in the select list of your query returns a boolean, so the query will only return 0, 1 or NULL for every row in the table.
SELECT SUBSTRING(documentnumber, 1) LIKE '%RCV%'
FROM transactionheader
For every row in the table, the first character of documentnumber will be inspected to see if it contains the string 'RCV', which will never be true. The query is going to return 0 or NULL for every row.
There is more than one query that will return documentnumber that start with 'RCV'. Here is one example:
SELECT h.documentnumber
FROM transactionheader h
WHERE h.documentnumber LIKE 'RCV%'
The WHERE clause specifies the conditional tests that will be performed on each row, only rows that "satisfy" the predicate will be returned.
Your original query has no WHERE clause so everything is being selected. Also, I would recommend using REGEXP instead. Here is my rewritten example.
SELECT substring(documentnumber, 1)
FROM transaction header
WHERE documentnumber REGEXP '^RCV'
;

How to return NULL when result is empty?

I have a simple query that selects one field and only one row, thus one value.
Is there any way to make it return NULL if the query results in an empty set? Instead of returning zero rows?
I think I need to use something with NOT EXISTS, THEN NULL but not certain about it.
select
(Your entire current Select statement goes here) as Alias
from
dual
dual is a built in table with a single row that can be used for purposes like this. In Oracle this is mandatory. MySQL supports it, but you can also just select a single value without specifying a table, like so:
select
(Your entire current Select statement goes here) as Alias
In either case you're selecting a single value. This means that:
If your select returns one value, that value is returned.
If your select statement returns one column, but no rows, NULL will be returned.
If your select statement returns multiple columns and/or multiple rows, this won't work and the query fails.
An easy way to do this is with aggregation:
select max(col)
from t
where <your condition here>
This always returns one row. If there is no match, it returns NULL.
Late reply but I think this is the easiest method:
SELECT
IFNULL((SELECT your query), NULL)
Use a UNION with a NOT EXISTS(original where clause)
select col1
from mytable
where <some condition>
union
select null
where not exists (
select * from mytable
where <some condition>)
You can use COALESCE for example:
SELECT COALESCE(Field1,NULL) AS Field1 FROM Table1
Edit 1:
sorry i mistake with return field as null not result set,for result set return as null use Union and Exist Function like this:
SELECT NULL AS Field1 FROM Table1 WHERE not EXISTS(SELECT Field1 FROM Table1 WHERE Field2>0)
UNION
SELECT Field1 FROM Table1 WHERE Field2>0

Mysql AVG to ignore zero

I need to perform an avg on a column, but I know that most of the values in that column will be zero. Out of all possible rows, only two will probably have positive values. How can I tell mySQL to ignore the zeros and only average the actual values?
Assuming that you might want to not totally exclude such rows (perhaps they have values in other columns you want to aggregate)
SELECT AVG(NULLIF(field ,0))
from table
You could probably control that via the WHERE clause:
select avg( field ) from table where field > 0
select avg(your_column)
from your_table
where your_column != 0
You can convert zeros to NULL, then AVG() function will work only with not NULL values.
UPDATE table SET column = NULL WHERE column='0';
SELECT AVG(column) FROM table;