I have query
SELECT all_users,
employed_users,
SUM(CASE WHEN (employment_one_terminated = 1 OR employment_two_terminated = 1) THEN 1 ELSE 0 END) AS unemployed_users
FROM users
WHERE status = 1
I added filter to the webpage unemployed_min and unemployed_max numeric, is there way to filter in MySQL only without involving PHP say when you select on page
unemployed_min = 1
unemployed_max = 5
when i do
SELECT all_users,
employed_users,
SUM(CASE WHEN (employment_one_terminated = 1 OR employment_two_terminated = 1) THEN 1 ELSE 0 END) AS unemployed_users
FROM users
WHERE status = 1
AND unemployed_users > 1 AND unemployed_users < 5
or
SELECT all_users,
employed_users,
SUM(CASE WHEN (employment_one_terminated = 1 OR employment_two_terminated = 1) THEN 1 ELSE 0 END) AS unemployed_users
FROM users
WHERE status = 1
AND SUM(CASE WHEN (employment_one_terminated = 1 OR employment_two_terminated = 1) THEN 1 ELSE 0 END) > 1
AND SUM(CASE WHEN (employment_one_terminated = 1 OR employment_two_terminated = 1) THEN 1 ELSE 0 END) < 5
does not work
EDIT:
it saying "Invalid use of group function" however i dont use group statement
You are looking for the having clause, because you want to filter on an aggregated expression:
SELECT all_users,
employment_terminated,
unemployment_collected,
SUM(CASE WHEN (employment_one_terminated = 1 OR employment_two_terminated = 1) THEN 1 ELSE 0 END) AS unemployed_users
FROM users
WHERE status = 1
HAVING unemployed_users > 1 AND unemployed_users < 5;
There is a serious grouping issue with your queries. You're using an aggregated function and not grouping by any field while selecting a few. That means you will only get one row containing an unpredictable value in all_users and employed_users.
First, you will have to define the proper grouping (maybe this?)
GROUP BY all_users, employed_users
Then, if you need to filter the groups you can use the HAVING clause:
HAVING unemployed_users > 1 AND unemployed_users < 5
You can also simplify the SUM this way:
SUM(employment_one_terminated = 1 OR employment_two_terminated = 1)
You can even remove the = 1 if those are boolean values.
The final query should look very similar to this:
SELECT all_users, employed_users,
SUM(employment_one_terminated OR employment_two_terminated) AS unemployed_users
FROM users
WHERE status = 1
GROUP BY all_users, employed_users
HAVING unemployed_users > 1 AND unemployed_users < 5
Related
I have a table with some columns (see the pic below):
My Table:
I'd like to count values in that columns (how many "ok" and "no" I have in column over05, over15, etc etc) using some filters (i.e. best_bets between 1.20 and 1.50) and show them using php
Now I can do a count just for a column using code below:
$result=mysql_query("SELECT count(over15) as total from risultati WHERE over15 = 'OK' AND best_bets >= 1.15 AND best_bets <= 1.50");
$data=mysql_fetch_assoc($result);
echo $data['total'];
but I'd like to do it for more columns
Regards
EDIT:I tried in this way, but it's not working:
$result=mysql_query("SELECT SUM(CASE WHEN over05 = 'OK' THEN 1 ELSE 0 END) AS OK_05,
SUM(CASE WHEN over15 = 'OK' THEN 1 ELSE 0 END) AS OK_15,
SUM(CASE WHEN over25 = 'OK' THEN 1 ELSE 0 END) AS OK_25,
SUM(CASE WHEN over35 = 'OK' THEN 1 ELSE 0 END) AS OK_35,
SUM(CASE WHEN over45 = 'OK' THEN 1 ELSE 0 END) AS OK_45
FROM risultati
WHERE best_bets BETWEEN 1.15 AND 1.5O");
$data=mysql_fetch_assoc($result);
echo $data['OK_15'];
echo $data['OK_25'];
echo $data['OK_35'];
echo $data['OK_45'];
edit2: I also tried in another way, but nothing:
$result=mysql_query("SELECT SUM(CASE WHEN over05 = 'OK' THEN 1 ELSE 0 END) AS OK_05,
SUM(CASE WHEN over15 = 'OK' THEN 1 ELSE 0 END) AS OK_15,
SUM(CASE WHEN over25 = 'OK' THEN 1 ELSE 0 END) AS OK_25,
SUM(CASE WHEN over35 = 'OK' THEN 1 ELSE 0 END) AS OK_35,
SUM(CASE WHEN over45 = 'OK' THEN 1 ELSE 0 END) AS OK_45
FROM risultati
WHERE best_bets BETWEEN 1.15 AND 1.5O");
while ($row = mysql_fetch_assoc($result))
{
echo $row['OK_05'];
echo $row['OK_15'];
echo $row['OK_25'];
echo $row['OK_35'];
echo $row['OK_45'];
}
Use condtional aggregation:
SELECT SUM(CASE WHEN over05 = 'OK' THEN 1 ELSE 0 END) AS OK_05,
SUM(CASE WHEN over15 = 'OK' THEN 1 ELSE 0 END) AS OK_15,
SUM(CASE WHEN over25 = 'OK' THEN 1 ELSE 0 END) AS OK_25,
SUM(CASE WHEN over35 = 'OK' THEN 1 ELSE 0 END) AS OK_35,
SUM(CASE WHEN over45 = 'OK' THEN 1 ELSE 0 END) AS OK_45
FROM risultati
WHERE best_bets BETWEEN 1.15 AND 1.5O -- or whatever restrictions you want
This approach allows you to gather stats for all your age columns in a single query, whereas putting the column check for 'OK' limits to a single column in one query.
I want to do math in a query, and was wondering if its better to do it in PHP or MYSQL.
Also, if I choose MYSQL can anyone help me with the query.
So far I have
SELECT COUNT(*) as total, booker, appdate,
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) book,
SUM(CASE WHEN status!='DNS' THEN 1 ELSE 0 END) tot
FROM appts WHERE WEEK(app_date)= WEEK(CURDATE()) GROUP BY booker
I want one more stat from this query.
I want to do book / (book+tot)
But obviously only if book!=0 or tot!=0, since obviously I don't want to divide anything by zero.
Is there a way to do this in a MYSQL query??
I want my output to be.....
book | 14
tot | 25
hold | 35%
Id also like to ORDER BY the hold percent from highest to lowest. Is this possible????
You can achieve what you ask for using a subquery, like this:
SELECT *, IF(book + tot, 100*book/(book + tot), NULL) AS hold
FROM (
SELECT COUNT(*) as total, booker, appdate,
SUM(status='DNS') book, SUM(status!='DNS') tot
FROM appts WHERE WEEK(app_date)= WEEK(CURDATE()) GROUP BY booker
) AS subquery
ORDER BY hold DESC
Note that in several places I'm using the fact that MySQL uses numbers for logical values. So you can sum up conditions without CASE, and you can write a formula for IF without <> 0 check.
Naive method:
SELECT
COUNT(*) as total,
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) book,
SUM(CASE WHEN status!='DNS' THEN 1 ELSE 0 END) tot,
IF( ( SUM(CASE WHEN status!='DNS' THEN 1 ELSE 0 END) +
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) ) = 0,
0,
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) /
( SUM(CASE WHEN status!='DNS' THEN 1 ELSE 0 END) +
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) )
) AS hold
FROM appts
WHERE WEEK(app_date) = WEEK(CURDATE()) GROUP BY booker
ORDER BY hold;
Or in order not to repeat your aliases, use a subquery:
SELECT *, IF (book + tot = 0, 0, book / (book + tot) * 100)
FROM (
SELECT
COUNT(*) as total,
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) book,
SUM(CASE WHEN status!='DNS' THEN 1 ELSE 0 END) tot,
FROM appts
WHERE WEEK(app_date) = WEEK(CURDATE()) GROUP BY booker
) AS subq
ORDER BY hold;
Or, more cleverly :) (book + tot = total)
SELECT *, IF (total = 0, 0, book / total * 100)
FROM (
SELECT
COUNT(*) as total,
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) book,
SUM(CASE WHEN status!='DNS' THEN 1 ELSE 0 END) tot,
FROM appts
WHERE WEEK(app_date) = WEEK(CURDATE()) GROUP BY booker
) AS subq
ORDER BY hold;
And, just for fun, the hackishly compactest form:
SELECT *, COALESCE(book / total * 100, 0) AS hold -- a division by 0 returns NULL
FROM (
SELECT
COUNT(*) total,
SUM(status='DNS') book, -- boolean "true" is internally integer "1"
SUM(status!='DNS') tot,
FROM appts
WHERE WEEK(app_date) = WEEK(CURDATE()) GROUP BY booker
) AS subq
ORDER BY hold;
$pos = select * from score_history where content_id = 6 && val = 1
$neg = select * from score_history where content_id = 6 && val = -1
i want to get the pos and neg scores in one query
but i dont want to use join
so perhaps some sort of IF/case statement ?
i've this but as you can guess it fails
SELECT count(*) as total ,
CASE
WHEN `val` = 1 THEN count(*) as `pos`
WHEN `val` = -1 THEN count(*) as `neg`
END
FROM score_history WHERE `content_id` = '46083' ";
is there any way to do this without using join or sub query ?
You can make use of the flexibility of MySQL to handle booleans and integers:
SELECT count(*) total, sum(val = 1) pos, sum(val = -1) neg
FROM score_history
WHERE content_id = '46083';
Whenever the condition is true it is a 1. Otherwise a 0. No CASE needed nor GROUP BY.
Close! A CASE statement doesn't return multiple columns, so you'll need 2 CASE statements and to wrap them in a SUM():
SELECT count(*) as total
,SUM(CASE WHEN `val` = 1 THEN 1 ELSE 0 END) as `pos`
,SUM(CASE WHEN `val` = -1 THEN 1 ELSE 0 END) as `neg`
FROM score_history WHERE `content_id` = '46083' ;
SELECT
SUM(CASE WHEN `val` = 1 THEN 1 ELSE O END) AS pos_count,
SUM(CASE WHEN `val` = -1 THEN 1 ELSE O END) AS neg_count
FROM score_history WHERE `content_id` = '46083';
Try this. Sorry I can't test, no database on this laptop.
select
count(*) as total,
sum(case val when 1 then 1 else 0 end) as pos,
sum(case val when -1 then 1 else 0 end) as neg
from score_history
where content_id = 6
Not sure if this is the best answer (and you would certainly want an index on your val column assuming there are many rows in the table) but this should certainly work - also assuming you only have 1 and -1 as values:
SELECT count(*), val from score_history where content_id = 6 group by val;
You were close; try the SUM function:
SELECT count(*) as total
, sum(CASE WHEN `val` = 1 THEN 1 ELSE 0 END) as `pos`
, sum(CASE WHEN `val` = -1 THEN 1 ELSE 0 END) as `neg`
FROM score_history
WHERE `content_id` = '46083';
select count(*)
from score_history
where content_id = 6 &&
(val = -1 or val=1)
group by val
I think this statement should work but I have tested on DBMS.
SELECT count(*) as total ,
count(case when val = 1 then 1 else null end) as pos,
count(case when val = -1 then 1 else null end) as neg
FROM score_history
WHERE `content_id` = '46083';
See SQLFIDDLE
Okay, a lot of these answers are close, but whenever you use an aggregate function you should use a group by.
SELECT count(*) as total
, (CASE WHEN `val` >= 0 THEN 'positive' ELSE 'negative' END) as interpreted_value
END
FROM score_history
WHERE `content_id` = '46083'
GROUP BY (CASE WHEN `val` >= 0 THEN 'positive' ELSE 'negative' END);
If you want to read up on how to use group by and aggregate functions here: https://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html
I want to fetch 2 coulmns count and do their total as a new column.
How can I do this?
i wrote this query, but this is returning wrong total.
SELECT count(case when `status`='1' then 1 else 0 end) AS HOT,
count(case when `status`='5' then 1 end)
AS Special_Case,count(case when 1=1 then 1 end) AS TOTAL
FROM `tbl_customer_conversation` group by
date(`dt_added`),user_id
COUNT will only give the times a record is matched, which in your query will always return 1. Because the values can either be 1 or 0. So count(1) is also 1 and count(0) is also 1.
AS, you want the total number of HOT cases and SPECIAL_CASE you have to use SUM.
SELECT
SUM(case when `status`='1' then 1 else 0 end) AS HOT,
SUM(case when `status`='5' then 1 end) AS Special_Case,
SUM(case when `status` = '1' or `status` = '5' then 1 end) AS TOTAL
FROM `tbl_customer_conversation`
group by date(`dt_added`),user_id
<?php
$inventory_in = $db->get_one("SELECT COALESCE(SUM(Qty), 0)
FROM inventory Where id=12 AND inv_type = 'in' LIMIT 1");
$inventory_out = $db->get_one("SELECT COALESCE(SUM(Qty), 0)
FROM inventory Where id=12 AND inv_type = 'out' LIMIT 1");
$inventory = $inventory_in - $inventory_out;
?>
Possible to combine two queries into one?
Thank you.
Assuming you want both values output you can use SUM/CASE
SELECT
COALESCE(SUM(CASE WHEN inv_type = 'in' THEN Qty ELSE 0 END ), 0) as Sum1,
COALESCE(SUM(CASE WHEN inv_type = 'out' THEN Qty ELSE 0 END ), 0) as Sum2
FROM inventory
WHERE id=12
LIMIT 1
You may want to add and inv_type in ('in', 'out') to your where clause but its not required.
How about a conditional sum?
SELECT
SUM(CASE WHEN inv_type = 'in' THEN 1 ELSE 0 END) InSum
SUM(CASE WHEN inv_type = 'out' THEN 1 ELSE 0 END) OutSum
WHERE
id = 12
Or if you just want the result
SELECT
SUM(CASE inv_type WHEN 'in' THEN 1 WHEN 'out' THEN -1 ELSE 0 END) TotalSum
WHERE
id = 12
SELECT inv_type, COALESCE(SUM(Qty), 0)
FROM inventory
WHERE id=12 AND inv_type IN ('in', 'out')
GROUP BY inv_type