COUNT in CASE statement? - mysql

I would like to categorize records based on the count of one field.
My code is :
select `posts`.`post_customer_fs_id` AS `post_customer_fs_id`,count(`post_id`) AS `open_post_count`,
CASE count(`post_id`)
WHEN count(`post_id`)=1 THEN 'A'
WHEN count(`post_id`)>1 THEN 'B'
END AS AAA
from `posts` where (`posts`.`post_status` = '3') AND posts.post_type_id='1' group by `posts`.`post_customer_fs_id` ;
For some reason I m receiving A for the records with COUNT 1 but NULL for the records with COUNT bigger than 1.
The post_id is an INTEGER field..
Any help it will be very appreciated!

In
CASE count(post_id)
WHEN count(post_id)=1 THEN 'A'
You are comparing count(post_id) with count(post_id)=1 where the latter results in true or false which equals 1 or 0 in MySQL. You want
CASE
WHEN count(post_id)=1 THEN 'A'
instead.

TRY :::
select post_customer_fs_id AS 'post_customer_fs_id', count(post_id) AS 'open_post_count',
CASE
WHEN count(post_id)=1 THEN 'A'
WHEN count(post_id)>1 THEN 'B'
ELSE 'C'
END AS 'AAA'
from posts where post_status = '3' AND post_type_id= '1'
group by post_customer_fs_id ;

Related

max(case when ...) syntax issue

select
complaint_id
,complaint_type
,COMMUNICATION_ID
,max(case when delivery_type='deliver_once' then '1' else '0' end as IS_ADDON_REFUND)
from
complaints_order_status
group by 1,2,3
what's the issue with it?
You can't name your column inside the MAX function. Also use integers for 1 and 0. Also, if you could paste in the error message you're getting it would be helpful. But try:
select complaint_id ,
complaint_type ,
COMMUNICATION_ID ,
max(case when delivery_type='deliver_once' then 1 else 0 end) as IS_ADDON_REFUND
from complaints_order_status
group by complaint_id ,complaint_type ,COMMUNICATION_ID
I have changed two things from your code:
Use the alias in Group by. 1,2,3 don't work on all platforms.
Give alias outside max clause bracket. There is no need to give a name to
case when clause when this is not your final output.
Here is the final code:
select complaint_id ,complaint_type ,COMMUNICATION_ID ,
max(case when delivery_type='deliver_once'
then '1' else '0'
end )as IS_ADDON_REFUND
from complaints_order_status
group by complaint_id,
complaint_type,
COMMUNICATION_ID

Decide the output if a value exists in the group after SQL grouping

id, number, user and status are my columns
Here, the column "status" is having enum values 'A','D','P' and 'R'
SELECT
number,
count(user),
status
FROM
table1
GROUP BY
number
ORDER BY
id DESC
I'm grouping the results from the column "number" and if any record of the group contains 'P' for the "status" the result must be 'P', Else the result must be the Maximum value in alphabetical order
You can do it with conditional aggregation:
SELECT number,
COUNT(user) counter,
COALESCE(MAX(CASE WHEN status = 'P' THEN status END), MAX(status)) status
FROM table1
GROUP BY number
If any of the values of status for a specific number is 'P' then MAX(CASE WHEN status = 'P' THEN status END) will return 'P' and if none of them is 'P' it will return NULL.
So COALESCE() will return 'P' for the first case or MAX(status) for the second case.
Compute auxiliary value holding information if there exists 'P', then decide by this value:
SELECT
case
when sum(case when status = 'P' then 1 else 0 end) > 0 then 'P'
else max(status)
end,
number
FROM
table1
GROUP BY
number
Please state your db vendor. For example in case of Postgres, count(*) filter (where ...) could be used too.

how to get the desired result based on some certain condition in sql using case?

I have a table which traces the users records I want to know which are the complete and process users's records based on their status
Here is the sql query
SELECT users.UserID,users.UserName,users.FirstName,users.LastName,users.Email,
CASE WHEN inword.inword_status = '3' THEN count(*) END As 'Process' ,
CASE WHEN inword.inword_status = '4' THEN count(*) END AS 'Complete'
FROM tbl_user users
INNER JOIN tbl_inword inword on users.UserID=inword.UserID
Where inword.Status=1 and users.Status=1 and
inword.CreatedDate BETWEEN '2020-10-01' and '2020-10-31' and inword.inword_status in (3)
group by users.UserID
Here is Query Output
My Expected result is
UserID Name Total Process Complete
1 Umair 1 1 0
1 Basit 20 20 0
1 Zaidi 34 32 2
Any Help would be Appreciated
You're not doing your conditional aggregation correctly, you should use something like:
COUNT(CASE WHEN inword.inword_status = '3' THEN inword.UserId END) As 'Process' ,
COUNT(CASE WHEN inword.inword_status = '4' THEN inword.UserId END) AS 'Complete'
Or you can take advantage of MySQL treating booleans as 1 or 0 in a numeric context and simplify to:
SUM(inword.inword_status = '3') As 'Process' ,
SUM(inword.inword_status = '4') AS 'Complete'

MySQL Division From Same Column with Different Keys

I have a table with 5 fields
id = this is autoincrementing field
form_id = this field is the form being filled out
entry_id = this is the identifier of the entry
meta_key = this is the identifier of the specific form fields
meta_value = this is the value entered into the form field
If I do a:
SELECT SUM(meta_value) FROM tbl WHERE meta_key = 55;
I get the sum of all the people who like apples.
If I do a:
SELECT SUM(meta_value) FROM tbl WHERE meta_key = 75;
I get the sum of all the people total.
I am trying to write one query that will give me the % of people who like apple so in essence ((RESULT of Q1) / (RESULT of Q2)) * 100
So far I've looked into self joins and subqueries but I'm essentially stuck now because all the tutorials on subqueries focus on the WHERE clause.
Simplest thing I can think of:
SELECT
(SELECT SUM(meta_value) FROM tbl WHERE meta_key = 55) /
(SELECT SUM(meta_value) FROM tbl WHERE meta_key = 75) * 100
as percentage;
Would that work for you?
You can try this query, it avoid any possibility of division by zero, just in case total = 0.
SELECT
CASE
WHEN b.sum_b IS NULL OR b.sum_b = 0 THEN 0
ELSE (a.sum_a / b.sum_b) * 100
END as percent
FROM (
SELECT SUM(meta_value) as sum_a FROM tbl WHERE meta_key = 55
) a,
(
SELECT SUM(meta_value) as sum_b FROM tbl WHERE meta_key = 75
) b
You can use conditional aggregation
SELECT (SUM(CASE WHEN meta_key = 55 THEN meta_value ELSE 0 END) /
SUM(CASE WHEN meta_key = 75 THEN meta_value ELSE 0 END)) * 100 -- be careful you may got divide by zero error
FROM tbl
WHERE meta_key IN (55, 75);
However, this would produce integer division result. So, you can include 1.0 before division if you want exact result.
To avoid division by zero, I would simply recommend:
SELECT (SUM(CASE WHEN meta_key = 55 THEN meta_value ELSE 0 END) /
SUM(CASE WHEN meta_key = 75 THEN meta_value END)
) * 100
FROM tbl
WHERE meta_key IN (55, 75);
Note that the second CASE has no ELSE. If there are no matches, then this returns NULL, avoiding the divide-by-zero.
That said, MySQL does not return an error for divide-by-zero. It simply returns NULL. But that is highly database-specific behavior. I think every other database returns an error and you should be conscious of such potential issues.

get count of two table fields in one query

I am trying to get the count of females and males in the gender field of a table.
Is there a way to get the count of each in one query?
Something like:
select * from table count(where gender = 'm') as total_males, count(where gender = 'f') as total_females;
or will it require two queries?
select count(*) from table where gender = 'm';
select count(*) from table where gender = 'f';
This is basically a PIVOT. MySQL does not have a pivot so you can use an aggregate function with a CASE statement to perform this:
select
sum(case when gender = 'm' then 1 else 0 end) Total_Male,
sum(case when gender = 'f' then 1 else 0 end) Total_Female
from yourtable
See SQL Fiddle with Demo
Or using COUNT:
select
count(case when gender = 'm' then 1 else null end) Total_Male,
count(case when gender = 'f' then 1 else null end) Total_Female
from yourtable;
See SQL Fiddle with Demo
Something like this will work:
SELECT SUM(IF(t.gender='m',1,0)) AS total_males
, SUM(IF(t.gender='f',1,0)) AS total_females
FROM mytable t
The "trick" here is that we are using a conditional test to return either a 0 or a 1 for each row, and then adding up the 0's and 1's. To make this a little more clear, I am using the SUM aggregate function rather than COUNT, although COUNT could be used just as easily, though we'd need to return a NULL in place of the zero.
SELECT COUNT(IF(t.gender='m',1,NULL)) AS total_males
, COUNT(IF(t.gender='f',1,NULL)) AS total_females
FROM mytable t
Consider that the two expressions in the SELECT list of this query:
SELECT COUNT(1)
, SUM(1)
FROM mytable t
Will return the same value.
If you want to avoid the MySQL IF function, this can also be done using the ANSI SQL CASE expression:
SELECT SUM( CASE WHEN t.gender = 'm' THEN 1 ELSE 0 END )) AS total_males
, SUM( CASE WHEN t.gender = 'f' THEN 1 ELSE 0 END )) AS total_females
FROM mytable t
select sum(case when gender='m' then 1 else null end) as total_males, sum(case when gender='f' then 1 else null end) as total_females from ...
Should work just fine!
If your only issue is to avoid two queries, you can always write two queries as subselects of one query.
Select (select 1 from dual) as one, (select 2 from dual) as two from dual
This would work for your scenario, too.