$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
Related
I'm now doing four separate queries to select the information i need.
f.e.
SELECT value FROM data where sensor=123 AND value_id=a
SELECT value FROM data where sensor=123 AND value_id=b
SELECT value FROM data where sensor=123 AND value_id=c
SELECT value FROM data where sensor=123 AND value_id=d
Now i'm experementing with some code. I don't know if on my right way but is such a thing possible:
SELECT value180,value181,value182,value183
FROM (
SELECT
MAX(CASE WHEN DATE(time) = subdate(CURDATE(), 1) THEN value ELSE 0 END) as value180,
MAX(CASE WHEN DATE(time) = subdate(CURDATE(), 1) THEN value ELSE 0 END) as value181,
MAX(CASE WHEN DATE(time) = subdate(CURDATE(), 1) THEN value ELSE 0 END) as value182,
MAX(CASE WHEN DATE(time) = subdate(CURDATE(), 1) THEN value ELSE 0 END) as value183
FROM data
WHERE sensor_id = 1605850
AND value_id IN ("1.8.0","1.8.1","1.8.2","1.8.3")
) a
It would be nice to have a single query...thx for helping in advance!
note: i have to use max value of each day per sensor per value. In the above first example this max function was just left out for simplification.
This is the table how it looks like:
as you can see there are hourly taken values for each value_id.
What i need:
I need the highest value of yesterday for defined value_id's.
f.e. 1.8.0 = 3726.12, 1.8.1 = 663.69, ...
With my combined query i'm getting wrong values but the format how i want to get the values is correct:
try
SELECT value FROM data
WHERE sensor=123 AND value_id IN ('a', 'b', 'c' , 'd');
or
SELECT value FROM data
WHERE sensor=123 AND value_id IN (SELECT DISTINCT value_id FROM data);
After a short walk through the nature to take a pause i was able to solve my problem.
SELECT
(SELECT MAX(CASE WHEN DATE(time) = subdate(CURDATE(), 1) THEN value ELSE 0 END) FROM data WHERE sensor_id = 1605850 AND value_id = "1.8.0") as value180,
(SELECT MAX(CASE WHEN DATE(time) = subdate(CURDATE(), 1) THEN value ELSE 0 END) FROM data WHERE sensor_id = 1605850 AND value_id = "1.8.1") as value181,
(SELECT MAX(CASE WHEN DATE(time) = subdate(CURDATE(), 1) THEN value ELSE 0 END) FROM data WHERE sensor_id = 1605850 AND value_id = "1.8.2") as value182,
(SELECT MAX(CASE WHEN DATE(time) = subdate(CURDATE(), 1) THEN value ELSE 0 END) FROM data WHERE sensor_id = 1605850 AND value_id = "1.8.3") as value183
that was all.
Here is the normal mysql query
SELECT SUM( Minutes ) as minsDecPrac, COUNT( DISTINCT (CAST(dtDateTime as DATE))) as playDecPrac FROM `tbl_atschool_timelog` WHERE `intuid` = 48876 AND `intGametypeId` = 2 AND `intGame` = 1
Here is the Output
minsDecPrac playDecPrac
17 1
Here is the query using CASE WHEN
SELECT SUM(CASE WHEN intGametypeId = 2 AND intGame =1 THEN Minutes ELSE 0 END) AS minsDecPrac COUNT(DISTINCT CASE WHEN intGametypeId = 2 AND intGame =1 THEN (CAST(dtDateTime as DATE)) ELSE 0 END) AS playDecPrac FROM `tbl_atschool_timelog` WHERE `intuid` = 48876
Here is the Output
minsDecPrac playDecPrac
17 2
The problem is that if i use CASE WHEN, the output of "playDecPrac"(dtDateTime ) is wrong.
I don't know what i am wrong. Please help me if anybody knows
This clause here:
COUNT(DISTINCT CASE WHEN intGametypeId = 2 AND intGame =1 THEN (CAST(dtDateTime as DATE)) ELSE 0 END)
counts the 0 from ELSE 0 as a distinct value, in addition to the dates. So the COUNT(DISTINCT ) is one higher than it should be.
You might try ELSE NULL.
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
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;
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