Not able to alias column name in nested case using sql query - mysql

In this code its able to alias each case statement separately like,
SELECT
id,
SUM(CASE
WHEN (a.place = 'CHN' AND a.salary = 20000)
THEN '1'
ELSE '0'
END) AS '20K Salary',
SUM(CASE
WHEN (a.place = 'CHN' and a.salary = 35000)
THEN '1'
ELSE '0'
END) AS '35K Salary'
FROM Employee a;
but when nested CASE statement is used,
SELECT
id,
SUM(CASE
WHEN (a.place = 'CHN')
THEN (CASE
WHEN a.salary = 20000
THEN '1'
ELSE '0'
END) AS '20K Salary',
(CASE
WHEN a.salary = 35000
THEN '1'
ELSE '0'
END) AS '35K Salary'
END)
FROM Employee a;
its not possible to execute the query

In the first set of code each case statement is part of the SELECT list (i.e. they are in a comma separated list following SELECT) so each returns a column. In the second set of code there is only one case statement in the SELECT list, the fact that it is nested has no impact on this. Also the syntax for the nested case isn't correct because the THEN part is followed by two expressions separated by commas which is not allowed.

Of course this is possible to do what you want. You want to create two columns, so each needs its own logic and its own alias:
SELECT id,
SUM(CASE WHEN a.place = 'CHN' AND a.salary = 20000 THEN 1 ELSE 0
END) as Salary_20K,
SUM(CASE WHEN a.place = 'CHN' AND a.salary = 35000 THEN 1 ELSE 0
END) as Salary_35K
FROM Employee a;
Note: Don't put numeric constants in single quotes. Only use single quotes for string and date constants.

Related

Diffrence between sum of two products > 0

I want to select the sum of T_No where Transactions are equal to R and subtract it by T_No where Transactions are equal to D and the answer of this should greater than zero for a CustomerID which would be a input (an int input declared in a stored procedure)
((Sum(T_No) where Transactions = R - Sum(T_No) where Transactions = D ) > 0) where CoustomerID = #input
Example : for ID = 1 it would be ((20+15) - 10) > 0
I Have tried so many things but either syntax is wrong, wrong value or it does not accept, and I am literally Stuck, this was my final attempt
SELECT
(select ( select Sum(T_No) where Transactions = R) - (select Sum(T_No) where Transactions = D) as C_T )
FROM CustomerTrans WHERE C_T > 0 ;
Conditional aggregation should help:
SELECT
SUM(CASE WHEN Transaction = 'R' THEN t_no ELSE 0 END) - SUM(CASE WHEN Transaction = 'D' THEN t_no ELSE 0 END)
FROM CustomerTrans
WHERE CoustomerID = #yourCustomerIdVariable
As you're writing a sproc you can assign the result of this to a variable and then decide what to do if the result is negative. (I would personally log an error for example, rather than just hide those results). If the result is null, then there were no transactions for that customer
ps; I used Transaction because that's what your screenshot showed, and I figured a screenshot is less likely to contain a typo than code with syntax errors. Adjust if required
you where kinda close, I would sum like you, only the syntax is a bit off, you can't have aggregate fields in Where, thats why you should use having, also case when syntax is not correct.
Select
CoustomerID,
Sum(case when Transactions = 'R' then T_No else 0 end) -
Sum(case when Transactions = 'D' then T_No else 0 end) as C_T
FROM CustomerTrans
group by CoustomerID
having (Sum(case when Transactions = 'R' then T_No else 0 end) -
Sum(case when Transactions = 'D' then T_No else 0 end))>0

SQL count when value = 1

I'm doing a select on two tables with this:
SELECT m.torneio, m.deck, m.top, m.lugar, sum( m.quantidade ) AS quantidade, m.formato AS formato, q.quantidade AS qtorneio, t.season AS season, sum( m.top ) AS totaltops, count( m.lugar = '1' ) AS venceu
FROM `metagame` AS m, quantidade AS q, torneios AS t
WHERE m.torneio = t.nome
AND m.torneio = q.nome
GROUP BY m.deck
My problem is that venceu is counting all instances instead of only the ones when lugar = 1. Why is that?
tried with sum() too with no good results too. How can i fix this?
I am surprised that count( m.lugar = '1' ) syntaxs but it does and returns the sames as count(*). You should probably change it to sum(case when lugar = 1 else 0 end) as venceu. You should also look closely at the group by to be sure it works as you expect (i suspect not).
count(x) does not accept an expression.
It's only counting how many times x is returned.
What you should do is check if m.lugar is 1 and yes add one to the counter else do nothing.
Inline checks can be done like so:
case when m.lugar = '1' then 1 else 0 end
Then add all the one you gets :
sum(case when m.lugar = '1' then 1 else 0 end)
Your final query should look like this:
SELECT
m.torneio,
m.deck,
m.top,
m.lugar,
sum( m.quantidade ) AS quantidade,
m.formato AS formato,
q.quantidade AS qtorneio,
t.season AS season,
sum( m.top ) AS totaltops,
sum(case when m.lugar = '1' then 1 else 0 end) AS venceu
FROM
`metagame` AS m,
quantidade AS q,
torneios AS t
WHERE
m.torneio = t.nome
AND m.torneio = q.nome
GROUP BY
m.deck
If I understand your question you can use this:
sum(case when m.lugar = '1' then 1 else 0 end)
or you can try having clause
SELECT column_name(s)
FROM table_name
WHERE condition
GROUP BY column_name(s)
HAVING condition
ORDER BY column_name(s);

How do I calculate the difference of two alias for sorting

Considering the following code:
SELECT SUM(w.valor),
SUM(CASE WHEN w.tipo = '+' THEN w.valor ELSE 0 END) AS total_credit,
SUM(CASE WHEN w.tipo = '-' THEN w.valor ELSE 0 END) AS total_debit,
w.clientUNIQUE,
c.client as cclient
FROM wallet AS w
LEFT JOIN clients AS c ON w.clientUNIQUE = c.clientUNIQUE
WHERE w.status='V'
GROUP BY w.clientUNIQUE
ORDER BY total_credit-total_debit
I'm trying to calculate the difference of two aliased calculated values for sorting purposes, but I'm getting the following error:
Reference 'total_credit' not supported (reference to group function)
What am I doing wrong and how can I order results by using the difference value between the two aliases?
You can't refer to columns by their alias in the same select expression, so there are 2 options...
Repeat the expressions in the order by (yuk):
ORDER BY
SUM(CASE WHEN w.tipo = '+' THEN w.valor ELSE 0 END) AS total_credit -
SUM(CASE WHEN w.tipo = '-' THEN w.valor ELSE 0 END) AS total_debit
Or easier on the brain and easier to maintain (DRY), order via a sub query:
select * from (
<your query without the ORDER BY>
) q
ORDER BY total_credit - total_debit

Reduce the number of queries

I have seperate queries but i need to reduce the no so put all in one
select count(applicant_id) as registered from student_application where filter_status=0 AND
select count(applicant_id) as filer_select from student_application where filter_status=1 AND
select count(applicant_id) as filter_reject from student_application where filter_status=2
but this shows some errors
Use CASE expression.
Query
select
count(case when filter_status = 0 then applicant_id else null end) as registered,
count(case when filter_status = 1 then applicant_id else null end) as filer_select,
count(case when filter_status = 2 then applicant_id else null end) as filer_reject
from student_application;
SQL Fiddle
You could also use group_by, with the where clause if you're looking for a subset rather than all possible values of filter_status:
SELECT filter_status, COUNT(*)
FROM student_application
WHERE filter_status in (0, 1, 2)
GROUP BY filter_status;

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.