Query to get different values depending on all column values - mysql

I have a table tasks with a status column The value of status can either be 0,1 or 2.
I need to implement the following logic:
If any value in status is 0 then the answer is 0.
If all values are 2 then the result is 2.
Otherwise the result is one.
Right now I'm doing this with 3 queries.
a) SELECT status FROM tasks
b) SELECT status FROM tasks WHERE status = 2;
c) SELECT status FROM tasks WHERE status = 0
So a) is for getting the total number of rows. Then I compare that to the number of rows given by b). If the match then the answer is 2. If they don't I do query c). If it is non-empty the answer is 0 otherwise the answer is 1.
Is there any way to write a single query for this? Or is there a better way of doing it?

You can do it using conditional aggregation:
SELECT CASE
WHEN s0 >= 1 THEN 0
WHEN sAll = s2 THEN 2
ELSE 1
END
FROM (
SELECT COUNT(*) AS sAll,
COUNT(CASE WHEN status = 0 THEN 1 END) AS s0,
COUNT(CASE WHEN status = 2 THEN 1 END) AS s2
FROM tasks ) t
The sub-query performs all counts required to apply your business logic. The outer query simply uses this info, to produce the required result.
It's a bit unclear from your description whether the first condition in the CASE takes precedence over the second. If not, then just switch the position of the two WHENs.

Try:
SELECT MIN(status) FROM tasks;
- since when all status values are 2, the minimum will be 2, when any value is 0 then the minimum will be 0 and otherwise the minimum wll be 1.

Use following
SELECT (case
when ((SELECT count(*) FROM tasks WHERE status = 0)>0) then 0
when ((SELECT count(*) FROM tasks WHERE status = 2)=(SELECT count(*) FROM tasks)) then 2
else 1 end) AS countOfStatus

Related

SELECT query that displays the name of each record once and the count of instances

Is it possible to write a SELECT query that displays the name of each record once and the count of how many instances of that record there are for certain criteria?
For example, If I have a table with the following records:
How can I get the SELECT query to display the following:
You can use conditional aggregation:
select customer,
sum( status = 'Disposed' ) as num_disposed,
sum( status = 'Transported' ) as num_transported
from t
group by customer;
MySQL treats boolean expressions like integers in a numeric context, with 0 for false and 1 for true. So, just adding up the boolean is a simple way to count the number of rows that match the condition.
you can use a group by on case ansum for case
select customer, sum(case when status ='disposed' then 1 else 0 end) count_disposed
sum(case when status ='trasposed' then 1 else 0 end) count_trasposed
from my_table
group by customer

Perform calculations on two rows from UNION query

I have the following query
SELECT count
FROM (
SELECT count(id) as count FROM listens
WHERE user='None'
UNION
SELECT count(id) as count FROM listens
WHERE user!='None'
) as details
which returns
count
36793
112755
I would like to perform the division on the two values (e.g. 36793 / 112755) so that the output from my query is
count
0.3263092546
You don't need union at all! Here is a much simpler way of writing the query:
SELECT sum(user = 'None') / sum(user <> 'None')
FROM listens;
MySQL treats a boolean expression as a number in a numeric context, with 0 for false and 1 for true. The above counts the number of values that match the conditions.
If you want to be verbose or to be compatible with other dialects of SQL, you can do:
SELECT (sum(case when user = 'None' then 1 else 0 end) /
sum(case when user <> 'None' then 1 end)
) as ratio
FROM listens;
I don't see a particular advantage to the verbosity if you are using MySQL, but the logic is equivalent.

want to get all dates but when there is one or more TDBUY = 1 then this date#TDBUY=0 not

I have a table with a date column and a column named TDBUY (which can be 0 or 1). Now I do following:
SELECT tradedate,aktienstat.TDBuyPerfection,count(*) as cc from
aktienstat group by TradeDate,TDBuyPerfection HAVING cc >= '0' ORDER
BY TradeDate desc limit 100;
And get:
I don`t want to display f.e. the 2018-02-08 or 2018-02-07 with 0 count (line 1 and line 3) because there are 1 count with 1 each. But if no TDBUY then the date should be displayed with 0 count.
Can anyone here tell me please how to do it?
THANKS
Edit: It works also fine with SUM instead of Count.
SELECT tradedate,aktienstat.TDBuyPerfection,sum(aktienstat.TDBuyPerfection) as summe from
aktienstat group by TradeDate ORDER
BY TradeDate desc limit 100;ยด
We can try doing this via a pivot query:
SELECT
tradedate,
CASE WHEN cnt_1 = 0 THEN 0 ELSE 1 END AS TDBuyPerfection,
CASE WHEN cnt_1 = 0 THEN cnt_0 ELSE cnt_1 END AS cnt
FROM
(
SELECT
tradedate,
COUNT(CASE WHEN TDBuyPerfection = 0 THEN 1 END) AS cnt_0,
COUNT(CASE WHEN TDBuyPerfection = 1 THEN 1 END) AS cnt_1
FROM aktienstat
GROUP BY tradedate
) t;
The pivot trick works here because it brings the zero and one counts into a single record. There, it is relatively easy to test both counts. In your current form, it is much harder to check the counts.
The demo below shows that zero buy dates appear with only the zero count, while dates having a buy count show only the buy data.
Demo

SQL query to count total ocurrences of values in one column and relative occurrence in another column

This is my first post, so any general corrections to format/content are also welcome. I'm relatively new to SQL.
Say I have a database which collects test results from an classification evaluation. I know what the expected outcome is for each test. I also have a column indicating whether the test was successful, ie the expected value returned matched the expected value. It looks something like this:
Expected_Result Result Success
A A True
A B False
B B True
A A True
B A False
I know I can return the total occurrences of each expected type withSELECT Expected_Result, COUNT(Expected_Result) FROM Evaluation_Results GROUP BY Expected_Result.
I know how to count the number of false detections for a specific expected outcome with SELECT COUNT(*) FROM Evaluation_Results WHERE Success = 'True' AND Expected_Result = 'A'
Where I'm struggling is combining the two. I would like the query to return a list of all distinct expected results, the total of each, the count of successful results, and the percentage of the total, like so:
Expected_Result Total Num_Successful Success_Rate
A 3 2 66.67
B 2 1 50.00
You could use a CASE expression to perform a condition check during aggregation. A case statement identifies a conditional outcome. For instance you could use:
select evaluation_result
, count(*) AS total
, sum(case when success='true' and result='a' then 1 else 0 end) AS num_successful
, sum(case when success='true' and result='a' then 1 else 0 end)/count(*) AS success_rate
from evaluation_results group by evaluation_result;
Basically what's happening there is you're taking a count(*) of all grades, a sum() of a 1 or 0 based on a conditional outcome, then performing the ratio math. There's no need for a join here. The CASE Expression is a powerful conditional statement which can be used in so many diverse ways.
Or for a more flexible solution have a look at this:
select evaluation_result
, count(*) AS total
, sum(case when success='true' and result=evaluation_result then 1 else 0 end) AS num_successful
, sum(case when success='true' and result=evaluation_result then 1 else 0 end)/count(*) AS success_rate
from evaluation_results group by evaluation_result;
You can use self join if table is same like.
SELECT distinct e.Expected_Result, COUNT(Expected_Result), sum(e1.columns name), avg(e1.column name)
FROM Evaluation_Results e
left join Evaluation_Results e1 on e1.col=e.col
GROUP BY e.Expected_Result
Use this simple Query and check for the result..
select Expected_Result, count(Expected_Result) Total,
sum(IF ('True' = Success, 1, 0) ) Num_Successful,
avg(IF ('True' = Success, 1, 0 )) Success_Rate
from Evaluation_Results group by Expected_Result

Several select count(*) in a single query

I have a mysql table(tbl_subscriptiondetails) like the above.Here the last column i.e
'test_status' could have possible values C,S & Y only.
Using a single query i would like to fetch data in the manner
as shown below
But the query that i'm using gives me undesired results.My query is
SELECT pkg_name,
(SELECT COUNT(*) FROM tbl_subscriptiondetails WHERE test_status='C' AND mem_id=3) AS completed,
(SELECT COUNT(*) FROM tbl_subscriptiondetails WHERE test_status='S' AND mem_id=3) AS started,
(SELECT COUNT(*) FROM tbl_subscriptiondetails WHERE test_status='Y' AND mem_id=3) AS remaining
FROM tbl_subscriptiondetails
WHERE mem_id=3
GROUP BY pkg_name
and the result is
Please advise what is wrong. Thanks in advance.
You are running a subquery for each count, instead of counting as part of the main query. Therefore, your filter conditions aren't behaving as you expect them to. You can change it like so, to do the conditional count:
SELECT pkg_name,
SUM( case when test_status='C' then 1 else 0 end) AS completed,
SUM( case when test_status='S' then 1 else 0 end) AS started,
SUM( case when test_status='Y' then 1 else 0 end) AS remaining
FROM tbl
WHERE mem_id = 3
GROUP BY pkg_name
Demo