How to include NULL values in aggregate function COUNT() in MySQL? - mysql

The aggregate query groups by attribute A3 and then performs a COUNT(A4) but it doesn't consider the NULL values in the attribute A4.

For a regular count, don't include the column name:
count(*)
For count distinct, just add the extra value back in:
count(distinct a4) + (case when count(a4) <> count(*) then 1 else 0 end)
This can be simplified in MySQL to:
count(distinct a4) + (count(a4) <> count(*))
Or, if you know there is value that won't exist in the column:
count(distinct coalesce(a4, ' <NULL>'))

Related

Difference Between Distinct Count() and Count(Distinct)

I have a Table Like so
user_id
status
1
true
1
true
2
false
2
true
Im Trying to Find the distinct count user_id where They are true and where they are false.
the query i have now is
SELECT
COUNT( DISTINCT CASE WHEN `status` = 'true' THEN 1 END ) AS `trues`,
COUNT( DISTINCT CASE WHEN `status` = 'false' THEN 1 END ) AS `false`,
FROM table
What is the difference between just removing Distinct from count and doing
SELECT DISTINCT
COUNT( CASE WHEN `status` = 'true' THEN 1 END ) AS `trues`,
COUNT( CASE WHEN `status` = 'false' THEN 1 END ) AS `false`,
FROM table
From the MySQL docs...
count
Returns a count of the number of non-NULL values of expr in the rows retrieved by a SELECT statement.
count(distinct)
Returns a count of the number of rows with different non-NULL expr values.
For example, if you have 1, 1, 1, 2, 3, null count will count 1,1,1,2,3 for 5 and count(distinct) will count 1,2,3 for 3.
select distinct
DISTINCT specifies removal of duplicate rows from the result set.
The key difference between select distinct count() and select count(distinct) is with select count(distinct) the distinct filter happens while counting, with select distinct count() the distinct filter happens after counting.
SELECT
COUNT( DISTINCT CASE WHEN `status` = 'true' THEN 1 END ) AS `trues`,
COUNT( DISTINCT CASE WHEN `status` = 'false' THEN 1 END ) AS `false`
FROM table;
This will always be 1 or 0.
The case statements will always result in 1 or null, so the results can only be something like 1,1,null,1,null. There's only 1 distinct non-null value to count, so the result is 1. If there's no matches it's null, null, null, there's no distinct non-null values so the result is 0.
SELECT DISTINCT
COUNT( CASE WHEN `status` = 'true' THEN 1 END ) AS `trues`,
COUNT( CASE WHEN `status` = 'false' THEN 1 END ) AS `false`,
FROM table
Here, because there is a single row, the distinct has no effect; there's only one row and it's always going to be distinct.
But if there were multiple rows, perhaps because there's a group by, it would only return those results which are distinct. For example, let's say without the distinct we get...
trues false
------------
1 1
1 1
1 2
2 2
2 2
Then select distinct will only return those rows which are distinct.
trues false
------------
1 1
1 2
2 2
Try it.

How to make this sql query work for multiple columns

I have a query structured like below, it checks if any of the entry in a given column is not null, if it finds a match (a value that is not null) it immediately returns Y, if all values are null it returns N. It works with a column called first_name but I need to make it work for other columns as well i.e last_name, middle_name, preferably all in a single query to save execution time. Y or N must be returned for each of the columns specified.
SELECT CASE
WHEN EXISTS(SELECT *
FROM (patient AS p JOIN patient_score AS s ON p.patient_id=s.patient_id)
WHERE first_name IS NOT NULL)
THEN 'Y'
ELSE 'N'
END AS your_result
I have another query which is an alternative and does the same job (1/0 instead of Y/N). But I don't know how to make it work with multiple columns either. A procedure that could work by supplying multiple column names would work as well.
SELECT COUNT(*) AS fn FROM
(SELECT 1
FROM (patient AS p JOIN patient_score AS s ON p.patient_id=s.patient_id)
WHERE first_name IS NOT NULL
LIMIT 1) AS T;
I think it is the query that you want, you have to add a SELECT element (CASE WHEN SUM(CASE WHEN column_name IS NULL THEN 0 ELSE 1 END) > 0 THEN 'Y' ELSE 'N' END AS column_name) for each column you want to check.
SELECT
CASE WHEN SUM(CASE WHEN first_name IS NULL THEN 0 ELSE 1 END) > 0 THEN 'Y' ELSE 'N' END AS first_name
FROM patient AS p
INNER JOIN patient_score AS s ON p.patient_id = s.patient_id

Counting individual items in MY SQL or MS SQL column

I have data with column name Rule1 with values ..Correct, Incorrect and Undefined
I was able to get the count of them in this particular column using Group BY
select Rule1, count(*) from table_name group by Rule1;
I have one more column Rule2 with Values Correct, Incorrect only
When I try a similar select statement as above, I am getting the only count of Correct and Incorrect
I want to get the count of Undefined as zero as no Undefined is present in Rule2 column
How to do that
How I can write a query that needs to show the count of fixed values in multiple columns
You can create a derived table that enumerates the possible values with union all, then bring your table with a left join:
select x.rule1, count(t.rule1) cnt
from (select 'Correct' rule1 union all select 'Incorrect' union all select 'Undefined') x
left join mytable t on t.rule1 = x.rule1
group by x.rule1
This is a cross-database syntax that will work in both MySQL and SQL Server.
In very recent versions of MySQL, you can use the values(row ...) syntax:
select x.rule1, count(t.rule1) cnt
from (values row('Correct'), row('Incorrect'), row('Undefined')) x(rule1)
left join mytable t on t.rule1 = x.rule1
group by x.rule1
In SQL Server, the equivalent query is:
select x.rule1, count(t.rule1) cnt
from (values ('Correct'), ('Incorrect'), ('Undefined')) x(rule1)
left join mytable t on t.rule1 = x.rule1
group by x.rule1
You could also use sum like this:
SELECT
sum(case when Rule1 = 'Correct' then 1 else 0 end) AS Rule1Correct,
sum(case when Rule1 = 'Incorrect' then 1 else 0 end) AS Rule1Incorrect,
sum(case when Rule1 = 'Undefined' then 1 else 0 end) AS Rule1Undefined,
sum(case when Rule2 = 'Correct' then 1 else 0 end) AS Rule2Correct,
sum(case when Rule2 = 'Incorrect' then 1 else 0 end) AS Rule2Incorrect
FROM
table_name
WHERE
1
It enables multiple counts in one query. I added all the counts, thought the first two was enough for the idea.
Futhermore I have no idea what is better for the serverload, this or using unions.

how to devide two counted values with different conditions Mysql

i want to make somthing like this :
SELECT COUNT(is_available = 1) / COUNT(*) FROM users;
but the condition of is_available = 1 doesn't reflect
it always gives result of "1"
Use CASE. For example:
select
sum(case when is_available = 1 then 1 else 0 end)
/
count(*)
from users;
Assuming is_available just takes two values, 0 and 1, you can use:
SELECT AVG(is_available)
FROM users;
If it can take other non-NULL values:
SELECT AVG(is_available = 1)
FROM users;
And, if you really need to counts NULLs, then you can use COALESCE() or:
SELECT SUM(is_available = 1) / COUNT(*)
FROM users;

What does "expr" do in MySQL's COUNT(expr) function?

Consider below:
SELECT COUNT(*) FROM table;
SELECT COUNT(1) FROM table;
SELECT COUNT(-2) FROM table;
SELECT COUNT(135392) FROM table;
SELECT COUNT(field) FROM table;
SELECT COUNT(field1 + field2) FROM table;
I am not clear on what expr actually does, or what it can be used for because all of the above SQL statements return the same result. Example below:
+-----------+
| count(..) |
+-----------+
| 54542 |
+-----------+
MySQL's manual (https://dev.mysql.com/doc/refman/8.0/en/counting-rows.html) does not go into very much detail on the expr part, other than using the * symbol
COUNT(<expr>) counts the number of rows where <expr> evaluates to a non-NULL values.
Generally, it is not needed with an expression and would only be used on a single, NULL-able column -- or column that could be NULL due to an outer join.
COUNT(*) will count all rows
COUNT(expr) will count the row if expr is NOT NULL
So COUNT(expr) could be less than COUNT(*) if expr contains NULL values:
SELECT COUNT(*), COUNT(1), COUNT(col)
FROM (
SELECT 'a' UNION ALL
SELECT 'b' UNION ALL
SELECT NULL
) AS t(col)
-- 3 3 2
Expr is short for expression, itself short for “some valid block of sql that results in a single value for this row when evaluated”
It could be a constant, a column, the result of a function call, variable assignment, case statement etc
—equivalent
COUNT(*)
COUNT(1)
COUNT(‘a’)
—count only males. If the group is 1000 in number and 600 are female, this returns 400
COUNT(case when gender = ‘m’ then ‘a’ else null end)
In supplement to the other answers, the <expr> may optionally start with the word DISTINCT in which case only unique occurrences of the referenced entity/expression/function result are counted
—in a set of 1000 animals, returns 1000
COUNT(gender)
—in a set of 1000 animals, 600 female, returns 2 (only values M and F exist in the group)
COUNT(distinct gender)