joining 3 or more table and sum the fields - mysql

I would like to join 3 tables.
The result is one of the field - SUM from the other table like this image, please help

You don't need to join tblwork as you can get all required fields from other 2 tables.
Following query should work:
select t1.nmstudent,
sum(case when t2.idwork = 'w001' then t2.trprice else 0 end) as w001,
sum(case when t2.idwork = 'w002' then t2.trprice else 0 end) as w002,
sum(case when t2.idwork = 'w003' then t2.trprice else 0 end) as w003,
sum(case when t2.idwork = 'w004' then t2.trprice else 0 end) as w004
from tblstudent t1
inner join tblTrans t2
on t1.idstudent = t2.idstudent
group by t1.idstudent;
Hope it helps!

Related

Appending data from different tables - mysql

I have the following tables Job description and Candidate.
Each job description can be related to n candidates. The candidates are obtained from different sources(a, b, c d) - candidate.source.
I want a single query to list me the JD ids, with count of candidates for each source for each JD, as shown below:
JD id | candidate name | count of candidates - source a | count of candidates - source b | count of candidates - source | c..............
Try using the query as a template:
select
JobDescriptionName,
SUM(ACount) CountOfCandidatesOfA ,
SUM(BCount) CountOfCandidatesOfB,
SUM(CCount) CountOfCandidatesOfC ,
SUM(DCount) CountOfCandidatesOfD
from
( select JobDescriptionID, (CASE WHEN Source = 'a' THEN 1 ELSE 0 END) AS ACount,
(CASE WHEN Source = 'b' THEN 1 ELSE 0 END) AS BCount,
(CASE WHEN Source = 'c' THEN 1 ELSE 0 END) AS CCount,
(CASE WHEN Source = 'd' THEN 1 ELSE 0 END) AS DCount
from Candidate) AS DerivedCandidate
inner join JobDescription ON JobDescription.JobDescriptionID = DerivedCandidate.JobDescriptionID group by JobDescriptionID;
I know there is already an accepted answer but in the effort of learning myself more about SQL here is an alternative way applying the case directly in the initial select without the sub-select:
Select
jd.id,
jd.name,
sum(case when c.source = 'a' then 1 else 0 end) as sourceA,
sum(case when c.source = 'b' then 1 else 0 end) as sourceB,
sum(case when c.source = 'c' then 1 else 0 end) as sourceC,
sum(case when c.source = 'd' then 1 else 0 end) as sourceD
from JobDescription as jd
join Candidate as c on c.jobId = jd.id
group by jd.id, jd.name
SQL Fiddle Demo
SELECT JD id, COUNT(Candidate), source
FROM table1
GROUP BY JD id,source

How to use user variable as counter with inner join queries that contains GROUP BY statement?

I have 2 tables odds and matches :
matches : has match_id and match_date
odds : has id, timestamp, result, odd_value, user_id, match_id
I had a query that get the following information from those tables for each user:
winnings : the winning bets for each user. (when odds.result = 1)
loses : the lost bets for each user.(when odds.result != 1)
points : the points of each user.(the sum of the odds.odd_value) for each user.
bonus : for each continuous 5 winnings i want to add extra bonus to this variable. (for each user)
How to calculate bonus?
I tried to use this query and I faced a problem : (you can check it here SQL Fiddle)
the calculated bonus are not right for all the users :
first user:(winnings:13, bonus=2).
second user:(winnings:8, bonus=2)bonus here should be 1.
third user:(winnings:14, bonus=3)bonus here should be 2.
why does the query not calculate the bonus correctly?
select d.user_id,
sum(case when d.result = 1 then 1 else 0 end) as winnings,
sum(case when d.result = 2 then 1 else 0 end) as loses,
sum(case when d.result = 1 then d.odd_value else 0 end) as points,
f.bonus
FROM odds d
INNER JOIN
(
SELECT
user_id,SUM(CASE WHEN F1=5 THEN 1 ELSE 0 END) AS bonus
FROM
(
SELECT
user_id,
CASE WHEN result=1 and #counter<5 THEN #counter:=#counter+1 WHEN result=1 and #counter=5 THEN #counter:=1 ELSE #counter:=0 END AS F1
FROM odds o
cross join (SELECT #counter:=0) AS t
INNER JOIN matches mc on mc.match_id = o.match_id
WHERE MONTH(STR_TO_DATE(mc.match_date, '%Y-%m-%d')) = 2 AND
YEAR(STR_TO_DATE(mc.match_date, '%Y-%m-%d')) = 2015 AND
(YEAR(o.timestamp)=2015 AND MONTH(o.timestamp) = 02)
) Temp
group by user_id
)as f on f.user_id = d.user_id
group by d.user_id
I am not sure how your result related to matches table,
you can add back WHERE / INNER JOIN clause if you need.
Here is link to fiddle
and the last iteration according to your comments:
And here is a query:
SET #user:=0;
select d.user_id,
sum(case when d.result = 1 then 1 else 0 end) as winnings,
sum(case when d.result = 2 then 1 else 0 end) as loses,
sum(case when d.result = 1 then d.odd_value else 0 end) as points,
f.bonus
FROM odds d
INNER JOIN
(
SELECT
user_id,SUM(bonus) AS bonus
FROM
(
SELECT
user_id,
CASE WHEN result=1 and #counter<5 AND #user=user_id THEN #counter:=#counter+1
WHEN result=1 and #counter=5 AND #user=user_id THEN #counter:=1
WHEN result=1 and #user<>user_id THEN #counter:=1
ELSE
#counter:=0
END AS F1,
#user:=user_id,
CASE WHEN #counter=5 THEN 1 ELSE 0 END AS bonus
FROM odds o
ORDER BY user_id , match_id
) Temp
group by user_id
)as f on f.user_id = d.user_id
group by d.user_id

joining with a group by and pivot

I have two tables as below
tbl1
id qNum
1 1
2 2
3 3
tbl2
id qNum displayNum
1 1 3
2 2 1
3 2 2
4 2 4
Ideally I need a sql results to look like this
qNum display1 display2 display3 display4
1 0 0 1 0
2 1 1 0 1
3 0 0 0 0
I have tried the following sql but this was not correct
SELECT
tbl1.qNum,
CASE when tbl2.displayNum=1 then 1 else 0 end AS filter1,
CASE when tbl2.displayNum=2 then 1 else 0 end AS filter2,
CASE when tbl2.displayNum=3 then 1 else 0 end AS filter3,
CASE when tbl2.displayNum=4 then 1 else 0 end AS filter4,
CASE when tbl2.displayNum=5 then 1 else 0 end AS filter5
FROM
tbl1
Left Join tbl2 ON tbl1.qNum = tbl2.qNum
GROUP BY
tbl1.qNum
Could anyone help a little please!!
You have use MAX function to pivot the table
Try this:
SELECT tbl1.qNum,
MAX(CASE WHEN tbl2.displayNum=1 THEN 1 ELSE 0 END) AS filter1,
MAX(CASE WHEN tbl2.displayNum=2 THEN 1 ELSE 0 END) AS filter2,
MAX(CASE WHEN tbl2.displayNum=3 THEN 1 ELSE 0 END) AS filter3,
MAX(CASE WHEN tbl2.displayNum=4 THEN 1 ELSE 0 END) AS filter4,
MAX(CASE WHEN tbl2.displayNum=5 THEN 1 ELSE 0 END) AS filter5
FROM tbl1
LEFT JOIN tbl2 ON tbl1.qNum = tbl2.qNum
GROUP BY tbl1.qNum
Your query is almost correct, you're just missing an aggregate function:
SELECT
tbl1.qNum,
MAX(CASE when tbl2.displayNum=1 then 1 else 0 end) AS filter1,
MAX(CASE when tbl2.displayNum=2 then 1 else 0 end) AS filter2,
MAX(CASE when tbl2.displayNum=3 then 1 else 0 end) AS filter3,
MAX(CASE when tbl2.displayNum=4 then 1 else 0 end) AS filter4,
MAX(CASE when tbl2.displayNum=5 then 1 else 0 end) AS filter5
FROM
tbl1
Left Join tbl2 ON tbl1.qNum = tbl2.qNum
GROUP BY
tbl1.qNum
The columns you select should always be either in the group by clause or an aggregate function should be applied to them. A group by "collapses" a group of rows and if you don't have an aggregate function on a column (which is not in the group by) a random row of that group is displayed.
Here you can read about the different aggregate functions: GROUP BY (Aggregate) Functions
The MAX() function in our case here returns the greatest value (note: not the row with the greatest value. You can also have a query like this: select min(col), max(col) from whatever).
I just want to point out that in MySQL, you can simplify the expression. It doesn't need a case statement because booleans are treated as integers with values of 0 and 1:
SELECT tbl1.qNum,
MAX(tbl2.displayNum = 1) AS filter1,
MAX(tbl2.displayNum = 2) AS filter2,
MAX(tbl2.displayNum = 3) AS filter3,
MAX(tbl2.displayNum = 4) AS filter4,
MAX(tbl2.displayNum = 5) AS filter5
FROM tbl1 Left Join
tbl2
ON tbl1.qNum = tbl2.qNum
GROUP BY tbl1.qNum;
Normally, I prefer going with ANSI standard syntax. I do, however, find this easier to read than the case syntax.
Also, you may not need tbl1 for the query, if all values you are interested in are already in tbl2.

Finding the Most current entry for a month using mysql

I am having a mysql problem I am trying to find both the most current payment value, and, for a particular month (in this query I'm using April). Link to the sqlfillde is here
(case when max(py.pay_date)and month(py.pay_date)= 4 then amount else 0 end) max_pay_april,
This is what I have but it doesn't seem to be working. The most current payment value is: (5, '2012-04-20', 90,) therefore it would be 90 I would really appreciate some help please.
How about this:
select p.name,
v.v_name,
sum(case when Month(py.pay_date) = 4 then amount end) april_amount,
max(case
when month(py.pay_date)= 4
and py.pay_date = (select max(pay_date)
from payment
where month(pay_date) =4 )
then amount else 0 end) max_pay_april,
sum(case
when Month(py.pay_date) = Month(curdate())
then amount end) current_month_amount,
sum(case
when Month(py.pay_date) = Month(curdate())-1
then amount end) previous_month_amount
from persons p
left join vehicle v
on p.id = v.person_veh
left join payment py
on p.id = py.person_id
group by p.name,
v.v_name
see SQL Fiddle with demo

subtract two values from two tables when null values exists

select p.partnerid,
sum(case when c.amount is not null then c.amount else 0 end) as amount,
sum(case when c.netamt is not null then c.netamt else 0 end) as total,
sum(case when (c.netamt - d.paidamount) is not null then (c.netamt - d.paidamount) else 0 end) as remainingamount,
sum(case when d.paidamount is not null then d.paidamount else 0 end) as paidamt
from customerinfo c
left join dailypayments d on c.accno = d.accno
right join partnerinfo p on c.partnerid = p.partnerid
where (d.paiddate is null or (d.paiddate >= '2011-3-15' and d.paiddate <= '2012-6-13')) and p.manager = 7 group by p.partnerid
from athe above query i need to subtract two values from two tables where there is no value in second table.
for better understanding see below image.
Use the IFNULL() function to remove the case and simplify your calculation:
sum(c.netamt - ifnull(d.paidamount, 0)) as remainingamount,