sql query with a count - mysql

im sure this is easy but im having a block I am trying to write some sql against a single table that has (simplified for example)
RunName, Result
foo, pass
foo, pass
foo, fail
foo, pass
boo, pass
boo, fail
boo, fail
soo, pass
I was a query that will return a count of pass or fail for each name
something like for fail
foo, 1
boo, 2
soo, 0
and for pass
foo, 3
boo, 1
soo, 1

Normally you'd do a simple COUNT and GROUP BY RunName, but that will not show "zero results" like soo's fails.
This should work even for zero results (on MySQL)
SELECT RunName, SUM(Result='fail')
FROM TableA
GROUP BY RunName;
Demo here.
Edit: As Aaron points out, that only works on MySQL, this works on SQL Server also;
SELECT RunName, SUM(CASE WHEN Result = 'fail' THEN 1 ELSE 0 END) as fails
FROM TableA
GROUP BY RunName
Demo here.
Edit2: As Marcus points out, it's may not be a very index friendly way of doing the query, so if you have a primary key you may be better off doing a self join with a count/group to get the correct result;
SELECT a.RunName, COUNT(b.Result)
FROM TableA a LEFT JOIN TableA b ON a.id=b.id AND b.Result='fail'
GROUP BY RunName
Demo here.

This is for all the fail results, just change the where clause for pass:
select RunName, count(Result)
from [tableName]
where Result = 'fail'
group by RunName

You need to use a group by.
Something like this
Select count(result), runname, result from sometable
group by runname, result
this should give you output like
count runname result
2 foo pass
3 foo fail

Is this what you want?
SELECT RunName, SUM(CASE WHEN Result = 'pass' THEN 1 ELSE 0 END) as NumPass,
SUM(CASE WHEN Result = 'fail' THEN 1 ELSE 0 END) as NumFail
FROM yourtable
GROUP BY RunName
If you want separate results for each then you can just do a filter on the where clause like so:
SELECT RunName, COUNT(1) as NumPass
FROM yourtable
WHERE Result = 'pass'
GROUP BY RunName
SELECT RunName, COUNT(1) as NumFail
FROM yourtable
WHERE Result = 'fail'
GROUP BY RunName

Try this for fail
select RunName, count(Result) as cnt
from your_table
where Result = 'fail'
group by RunName
and this for pass
select RunName, count(Result) as cnt
from your_table
where Result = 'pass'
group by RunName

Try this:
For Pass:
SELECT RunName, COUNT(*)
FROM TableName
GROUP BY Result
WHERE UPPER(Result) = 'PASS'
For Fail:
SELECT RunName, COUNT(*)
FROM TableName
GROUP BY Result
WHERE UPPER(Result) = 'FAIL'

Related

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.

MySQL query for opposite of GROUP BY or DISTINCT?

I have the answer below that worked fine for me:
now instead of selecting distinct or group by , I want to select all that records ext_no having value zero only.
How to modify this answer? I tried using order by but it's showing an error. Any help will be appreciated. Thanks in advance.
SELECT ext_no, MAX(value)
FROM test
GROUP BY ext_no
HAVING COUNT(*) > 2 AND
COUNT(*) = COUNT(CASE value WHEN 0 THEN 1 END)
There are a couple of ways you can achieve this. Using a couple of correlated subqueries in the WHERE clause or by JOINing to a table containing MAX(value) and COUNT(*) values for each value of ext_no:
Query 1
SELECT ext_no
FROM test t1
WHERE NOT EXISTS (SELECT *
FROM test t2
WHERE t2.ext_no = t1.ext_no AND value != 0)
AND (SELECT COUNT(*)
FROM test t3
WHERE t3.ext_no = t1.ext_no) > 2
The first subquery checks that this ext_no has no value other than 0. The second checks that there are more than 2 copies of this ext_no.
Query 2
In this query we apply all the conditions (no non-zero values of value and more than 2 copies of ext_no) in the JOIN condition.
SELECT t1.ext_no
FROM test t1
JOIN (SELECT ext_no, MAX(value) AS max_value, COUNT(*) AS count
FROM test
GROUP BY ext_no) t2
ON t2.ext_no = t1.ext_no AND t2.max_value = 0 AND t2.count > 2
Output (for both queries)
ext_no
12133
12133
12133
11505
11505
11505
11505
Demo on SQLFiddle

using select statement in then clause of case

I'm trying to include select statement in the then of case statement but the output is not as expected. I know there is different method to do this but can it be done the way i'm trying to do.
Using the following example data:
create table example(name varchar(10));
insert into example values
('abc'),('bcd'),('xyz');
I have tried this query (here is the fiddle):
select
case when ((select * from example where name='abc')>=1)
then (select * from example where name='abc')
else (select count(*) from example)
end
from example
But it outputs
3
3
3
Expected output if name='abc' exist
name
abc
if not the count(*)
Thanks in advance
Your subquery in the example is (select * from example where name='abc') which is a result set, not a scalar value. Currently it "works" because it is comparing the only column in the table to the value 1 but if you had more than one column in the table it would error out. Perhaps you intended (select count(*) from example where name='abc')?
Similarly, the THEN clause in a case can only be used to provide a single column value. In order to do this, perhaps you meant the following:
select
case when exists (select * from example where name='abc')
then (select name from example where name='abc')
else (select count(*) from example)
end
from example
But even here you will get three rows and there is no correlation between the rows in example and the result set, so I am not really sure what you're trying to do. I imagine there is a higher purpose though so I will leave it at that.
This should do the trick
select distinct
case when ((select count(name) from example where name='abc')>=1)
then (select * from example where name='abc')
else (select count(*) from example)
end
from example
Let me know if it works.
Point 1:
For the query, you are trying, the from example in the last will cause to loop through all the records and fetch all the records. To restrict that, you have to remove that.
Point 2:
You can't combine multi row select * in a true condition with a single row count(*) in a false condition. You should limit to select a single row.
Example:
select
case when ( select count(*) from example where name='abc' ) >= 1
then ( select * from example where name='abc' limit 1 )
else ( select count(*) from example )
end as name
No need to bother with the complex queries.
SELECT COUNT(*) AS ct
FROM example
GROUP BY name = 'abc'
ORDER BY name = 'abc' DESC
LIMIT 1;
If you really want to use CASE just for the sake of using it:
SELECT
CASE name
WHEN 'abc' THEN 'abc'
ELSE 'others'
END AS name, COUNT(*) AS ct
FROM example
GROUP BY name = 'abc'
ORDER BY name = 'abc' DESC
LIMIT 1;
Try below query, which will work even you enter a second duplicate row as value 'abc'. Mostly above suggested queries will not work as you enter this duplicate row while as per your query condition (>=1), there can be multiple rows for name as 'abc'.
SELECT
CASE WHEN b.cnt>=1
THEN a.name
ELSE (SELECT COUNT(*) FROM EXAMPLE)
END
FROM (SELECT DISTINCT NAME FROM EXAMPLE WHERE NAME='abc') a
JOIN (SELECT NAME,COUNT(*) AS cnt FROM EXAMPLE WHERE NAME='abc') b
ON a.name=b.name

MySQL select most occurring or average

I have a MySQL table from which I want to select:
1) Either "most occurring" value, if there is any prevailing
2) Or "average" value, if there is no most occurring value.
Example table 1:
value
1
2
3
4
All values are occurred equally, therefore I want to take AVG(`value`)
Example table 2:
value
1
2
2
3
Value 2 prevails, therefore I want to select the value 2.
What mysql query would do this?
Starting from Gordon's answer I tested and corrected the SQL query in SQL Fiddle:
SELECT IF(t4.numcnts = 1, t1.avgvalue, t2.topvalue) AS result
FROM (select avg(value) as avgvalue from test) t1
CROSS JOIN (select value as topvalue from test group by value order by count(*) desc limit 1) t2
CROSS JOIN join (select count(distinct cnt) as numcnts from
(select count(*) as cnt from test group by value) t3) t4
Here is the Fiddle with the two test tables (switch out test2 for test to see the result when a particular value prevails): http://sqlfiddle.com/#!2/76914/3
My changes were to use an IF instead of a CASEstatement in the SELECTclause and to add the necessary table aliases for the subselects.
The following approach calculates both values and then chooses between them:
select (case when numcnts = 1 then avgvalue else topvalue end)
from (select avg(value) as avgvalue from t) cross join
(select value as topvalue from t group by value order by count(*) desc limit 1) cross join
(select count(distinct cnt) as numcnts from (select count(*) as cnt from t group by value))
Note: if you have ties for the top, but other values as well, then an arbitrary value is returned. You don't specify what to do in this case.
Also, the SQL is untested, so it might have syntax errors.

Query to fetch counting field values

I have a MySQL table with 20 fields.
out of 20, 15 have 3 possible value like 0,NA,1+. i need to write a query to fetch each field count which has value > 0. is it possible to get it in single query.?
Thanks Guys.
Unless I'm missing something...
SELECT
COUNT(CASE WHEN c1<>'0' THEN 1 END) AS c1_count,
COUNT(CASE WHEN c2<>'0' THEN 1 END) AS c2_count,
-- ...
COUNT(CASE WHEN c15<>'0' THEN 1 END) AS c15_count
FROM t
select "column1", count(*) from your_table where value>0
union all
select "column2", count(*) from your_table where value>0
...
... // repeat until column20
interesting documentation :- http://dev.mysql.com/doc/refman/5.0/en/union.html