Query not running properly while having sum function - mysql

I am running a query:
select
iars.id,students.rollno,
students.name as name,
teachers.name as tname,
students.studentid,
t1.studentid,
sum(t1.obt) as obt1, sum(t1.benefits) as ben1, sum(t1.max) as max1,
(t2.obt) as obt2, (t2.benefits) as ben2, (t2.max) as max2,
(t3.obt) as obt3, (t3.benefits) as ben3, (t3.max) as max3,
(t4.obt) as obt4, (t4.benefits) as ben4, (t4.max) as max4,
(t5.obt) as obt5, (t5.benefits) as ben5, (t5.max) as max5
from groups,students
left join iars on iars.id
left join str on str.studentid=students.studentid
left join course on course.c_id=students.course
left join teachers on teachers.id=iars.teacherid
join sgm on sgm.studentid=students.studentid
left join semdef on month
left join sps on sps.studentid=students.studentid and iars.paperid=sps.paperid
left join `attndata` `t1` on ((t1.studentid=students.studentid) and iars.id=t1.iarsid and t1.mon=1)
left join `attndata` `t2` on ((t1.studentid=t2.studentid) and t2.mon = 2 and iars.id=t2.iarsid)
left join `attndata` `t3` on ((t2.studentid=t3.studentid) and t3.mon = 4 and iars.id=t3.iarsid)
left join `attndata` `t4` on ((t3.studentid=t4.studentid) and t4.mon = 5 and iars.id=t4.iarsid)
left join `attndata` `t5` on ((t4.studentid=t5.studentid) and t5.mon = 6 and iars.id=t5.iarsid)
where students.course='1' and students.status='regular' and sps.paperid='2' and
iars.courseid=students.course and iars.semester=str.semesterid and iars.paperid='2' and
str.semesterid='1' and str.sessionid='12' and groups.id=sgm.groupid
group by sps.studentid , teachers.id order by students.name
It's with grouping, like I want to have sum according to the months, but whenever I use sum, it gives me funny result.

If you want the sum by months, you should group by date with month. Grouping with student and teacher will give you more than one row per month and will result in funny result

Related

Count based on another count - MySQL

I have the following Set of tables and I want to get all the services, age ranges and genders and next to each three of them the count of recipients corresponding to them.
So far I came up with the statement below, and it works.
select s.service_name,s.service_id,g.gender_id,ag.age_range_id,count(r.recipient_id) Temp
from tbl_services s inner join tbl_gender g
inner join tbl_age_range ag
left join tbl_recipient_services rs on rs.service_id=s.service_id
left join tbl_recipient r on r.gender_id=g.gender_id and rs.recipient_id=r.recipient_id
and (year(sysdate())-year(r.recipient_birth_date) >= min_age and year(sysdate())-year(r.recipient_birth_date) <= max_age)
group by s.service_id,g.gander_id,ag.age_range_id
But I need to only count the recipients who have 2 or more services in the tbl_recipient_services and I'm stuck again.
Anyone has an idea to fix that?
First, your query would be clearer with cross joins:
select s.service_name, s.service_id, g.gender_id, ag.age_range_id,
count(r.recipient_id) as all_recipients
from tbl_services s cross join
tbl_gender g cross join
tbl_age_range ag left join
tbl_recipient_services rs
on rs.service_id = s.service_id left join
tbl_recipient r
on r.gender_id = g.gender_id and
rs.recipient_id = r.recipient_id and
year(sysdate()) - year(r.recipient_birth_date) >= min_age and
year(sysdate()) - year(r.recipient_birth_date) <= max_age)
group by s.service_id, g.gender_id, ag.age_range_id;
This returns all combinations of service/gender/age even if there are no matches.
Let's add another column. To do so, we'll use a subquery to count the number of services per recipient and then include that in the count:
select s.service_name, s.service_id, g.gender_id, ag.age_range_id,
count(r.recipient_id) as num_recipients,
sum(rs2.num_services >= 2) as num_recipients_2plus
from tbl_services s cross join
tbl_gender g cross join
tbl_age_range ag left join
tbl_recipient_services rs
on rs.service_id = s.service_id left join
tbl_recipient r
on r.gender_id = g.gender_id and
rs.recipient_id = r.recipient_id and
year(sysdate()) - year(r.recipient_birth_date) >= min_age and
year(sysdate()) - year(r.recipient_birth_date) <= max_age) left join
(select rs2.recipient_id, count(*) as num_services
from tbl_recipient_services rs2
group by rs2.recipient_id
) rs2
on rs2.recipient_id = r.recipient_id
group by s.service_id, g.gender_id, ag.age_range_id;
If you don't want the additional column, you can change the left joins to inner joins and remove the count(r.recipient_id).

Why the SQL view is not showing all the results from the UNION query?

I have created a view with 2 queries joined together with an UNION ALL. If I run the query without the view it would display all the expected results but if I run the view would not display all the expected results. It's displaying the results of the first query running the view. Why does it happen?
CREATE OR REPLACE VIEW V_TRAFFIC_ORDERS
as
"First query"
select date.id date_id1, date.date date, channel.channel_name, product.product_name, product.pay_type, orders.total,
orders.target,
0 as traffic,
0 as traffic_target /*Divided by 7 days to get a weekly target*/
from orders
inner join traffic on orders.date_id = traffic.date_id and orders.channel_id= traffic.channel_id
inner join channel on channel.id = orders.channel_id
inner join product on orders.product_id = product.id
inner join date on date.id = orders.date_id
left join traffic_target on traffic_target.week= date.week and
traffic_target.quarter= date.quarter and traffic_target.channel_id=orders.channel_id
UNION ALL
"Second query"
select date.id date_id2, date.date date, channel.channel_name, product.product_name,product.pay_type, IFNULL(freesim.total,0) as orders, 0 as orders_target, uvs as traffic, IFNULL((traffic_target.target/7),0) as traffic_target
from raw_coremetrics_page
left join V_FREESIM_ORDERS as freesim on freesim.`date`= raw_coremetrics_page.date
left join date on date.date=raw_coremetrics_page.date
left join traffic_target on traffic_target.week= date.week and
traffic_target.quarter= date.quarter and traffic_target.channel_id=5
inner join channel on channel.id = 5
inner join product on product.id = 3
where page like '%CHOOSER%' and category='CHOOSER'
Do with the following change:
CREATE OR REPLACE VIEW V_TRAFFIC_ORDERS
as
select * from (
select date.id date_id1, date.date date, channel.channel_name, product.product_name, product.pay_type, orders.total,
orders.target,
0 as traffic,
0 as traffic_target /*Divided by 7 days to get a weekly target*/
from orders
inner join traffic on orders.date_id = traffic.date_id and orders.channel_id= traffic.channel_id
inner join channel on channel.id = orders.channel_id
inner join product on orders.product_id = product.id
inner join date on date.id = orders.date_id
left join traffic_target on traffic_target.week= date.week and
traffic_target.quarter= date.quarter and traffic_target.channel_id=orders.channel_id
UNION ALL
select date.id date_id2, date.date date, channel.channel_name, product.product_name,product.pay_type, IFNULL(freesim.total,0) as orders, 0 as orders_target, uvs as traffic, IFNULL((traffic_target.target/7),0) as traffic_target
from raw_coremetrics_page
left join V_FREESIM_ORDERS as freesim on freesim.`date`= raw_coremetrics_page.date
left join date on date.date=raw_coremetrics_page.date
left join traffic_target on traffic_target.week= date.week and
traffic_target.quarter= date.quarter and traffic_target.channel_id=5
inner join channel on channel.id = 5
inner join product on product.id = 3
where page like '%CHOOSER%' and category='CHOOSER')

MS-Access Joining 2 Subqueries

Need a little help with subqueries
If I have a 1 query like this:
SELECT Learner.Learner_Id, Max(LearnerEmploymentStatus.DateEmpStatApp) AS LatestEmpDate, Learner.LearnRefNumber, Learner.FamilyName, Learner.GivenNames, EmploymentStatusMonitoring.ESMType
FROM (Learner LEFT JOIN LearnerEmploymentStatus ON LearnerEmploymentStatus.Learner_Id = LearnerEmploymentStatus.Learner_Id) LEFT JOIN EmploymentStatusMonitoring ON LearnerEmploymentStatus.LearnerEmploymentStatus_Id = EmploymentStatusMonitoring.LearnerEmploymentStatus_Id
WHERE EmploymentStatusMonitoring.ESMType="BSI"
GROUP BY Learner.Learner_Id, Learner.LearnRefNumber, Learner.FamilyName, Learner.GivenNames, EmploymentStatusMonitoring.ESMType
...and another like this:
SELECT Learner.Learner_Id, LearnerEmploymentStatus.DateEmpStatApp, EmploymentStatusMonitoring.ESMCode
FROM (Learner LEFT JOIN LearnerEmploymentStatus ON Learner.Learner_Id = LearnerEmploymentStatus.Learner_Id) LEFT JOIN EmploymentStatusMonitoring ON LearnerEmploymentStatus.LearnerEmploymentStatus_Id = EmploymentStatusMonitoring.LearnerEmploymentStatus_Id
...and I wanted to do a join between the 2 queries (LEFT JOIN on the common Learner_Id and LatestEmpDate / DateEmpStatApp fields), how would I go about doing all this work in a single query where the 2 queries above would be subqueries?
My attempt below is not being accepted (JOIN expression not supported):
SELECT sQ1.Learner_Id, sQ1.LearnRefNumber, sQ1.FamilyName, sQ1.GivenNames, sQ1.LatestEmpDate, sQ1.ESMType, sQ2.ESMCode
FROM
(SELECT Learner.Learner_Id, Max(LearnerEmploymentStatus.DateEmpStatApp) AS LatestEmpDate, Learner.LearnRefNumber, Learner.FamilyName, Learner.GivenNames, EmploymentStatusMonitoring.ESMType
FROM (Learner LEFT JOIN LearnerEmploymentStatus ON LearnerEmploymentStatus.Learner_Id = LearnerEmploymentStatus.Learner_Id) LEFT JOIN EmploymentStatusMonitoring ON LearnerEmploymentStatus.LearnerEmploymentStatus_Id = EmploymentStatusMonitoring.LearnerEmploymentStatus_Id
WHERE EmploymentStatusMonitoring.ESMType="BSI"
GROUP BY Learner.Learner_Id, Learner.LearnRefNumber, Learner.FamilyName, Learner.GivenNames, EmploymentStatusMonitoring.ESMType) As sQ1
LEFT JOIN
(SELECT Learner.Learner_Id, LearnerEmploymentStatus.DateEmpStatApp, EmploymentStatusMonitoring.ESMCode
FROM (Learner LEFT JOIN LearnerEmploymentStatus ON Learner.Learner_Id = LearnerEmploymentStatus.Learner_Id) LEFT JOIN EmploymentStatusMonitoring ON LearnerEmploymentStatus.LearnerEmploymentStatus_Id = EmploymentStatusMonitoring.LearnerEmploymentStatus_Id) As sQ2
ON (sQ1.Learner_Id = sQ2.Learner_Id) AND (sQ1.LatestEmpDate = sQ2.DateEmpStatApp);
Would something like this get you what you want...?
SELECT l.Learner_Id, d.LatestEmpDate, l.LearnRefNumber, l.FamilyName, l.GivenNames, m.ESMType, m.ESMCode
FROM ((Learner AS l
LEFT JOIN (
SELECT s.Learner_Id, MAX(s.DateEmpStatApp) AS LatestEmpDate
FROM LearnerEmploymentStatus AS s
GROUP BY s.Learner_Id) AS d ON d.Learner_Id = l.Learner_Id)
LEFT JOIN LearnerEmploymentStatus AS ls ON (ls.Learner_Id = d.Learner_Id) AND (ls.DateEmpStatApp = d.LatestEmpDate))
LEFT JOIN EmploymentStatusMonitoring AS m ON m.LearnerEmploymentStatus_Id = ls.LearnerEmploymentStatus_Id
WHERE m.ESMType = 'BSI'
Assumes the same learner won't have the same DateEmpStatApp twice, which may or not be valid.

Joining results of two independent query

I have two working queries:
1st returns the product list:
$sql = "
SELECT a.stockID, a.stockCatID, a.stockName, a.stockCode, a.stockCatCode,
CONCAT_WS(' » ', d.stockCatName, c.stockCatName, b.stockCatName) AS stockPath,
a.stockName AS stockTitle, a.stockID AS uniStock
FROM stockcards a
LEFT OUTER JOIN stockcategories b
ON a.stockCatID = b.stockCatID
LEFT OUTER JOIN stockcategories c
ON b.stockParentCat = c.stockCatID
LEFT OUTER JOIN stockcategories d
ON c.stockParentCat = d.stockCatID ";
2nd is basically returns the difference of total received and total sent whic is remaining quantity:
SELECT DISTINCT (COALESCE(o.totalReceived, 0) + COALESCE(p.totalSent, 0)) as RemainingStock
FROM deliverydetails k
INNER JOIN stockcards l ON k.stockID= l.stockID
LEFT JOIN
(
SELECT m.stockID, SUM(m.dQuantity) totalReceived
FROM deliverydetails m
WHERE m.dQuantity > 0
GROUP BY m.stockID
)
o ON k.stockID = o.stockID
LEFT JOIN
(
SELECT n.stockID, SUM(n.dQuantity) totalSent
FROM deliverydetails n
WHERE n.dQuantity < 0
GROUP BY n.stockID
)
p ON k.stockID = p.stockID
I need to add a new column to first query to display remanining quantity. But couldn't succeed to join this two. Thanks for any tip.
As it seems that your 2nd query just sums positive and negative dQuantities for each stockID, and then adds them together, I think this small change to your 1st query is
all that is needed:
SELECT a.stockID, a.stockCatID, a.stockName, a.stockCode, a.stockCatCode,
CONCAT_WS(' » ', d.stockCatName, c.stockCatName, b.stockCatName) AS stockPath,
a.stockName AS stockTitle, a.stockID AS uniStock,
dd.RemainingStock AS RemainingStock
FROM stockcards a
LEFT OUTER JOIN stockcategories b
ON a.stockCatID = b.stockCatID
LEFT OUTER JOIN stockcategories c
ON b.stockParentCat = c.stockCatID
LEFT OUTER JOIN stockcategories d
ON c.stockParentCat = d.stockCatID
LEFT OUTER JOIN
(SELECT stockID, SUM(dQuantity) AS RemainingStock
FROM deliverydetails
GROUP BY stockID) AS dd
ON dd.stockID = a.stockID

Joining 6 MySQL tables for sports application

I'm creating a database that is going to be used for a sporting competition. To view the results of a game, I need to join six tables together:
Season s
Round r
Rounddetails rd
Match m
Matchdetails md
Game g
I want the select statement to return something like this:
g.gameid, g.pointsfor, g.pointsagainst, md.matchdetailsid, m.matchid, rd.rounddetailsid, r.roundid, s.seasonid
Could anyone help me write a MySQL statement that will return that?
Please click the link to view the tables
EDIT: so far I have tried this query:
select
`s`.`seasonID` AS `seasonID`,
`r`.`roundID` AS `roundid`,
`rd`.`roundDetailsID` AS `roundDetailsID`,
`m`.`matchid` AS `matchid`,
`md`.`matchDetailsID` AS `matchDetailsID`,
`g`.`gameid` AS `gameid`,
`g`.`pointsfor` AS `pointsfor`,
`g`.`pointsagainst` AS `pointsagainst`
from (((((`season` `s` left join `round` `r` on((`s`.`SeasonID` = `r`.`SeasonID`)))
left join `rounddetails` `rd` on((`r`.`RoundID` = `rd`.`RoundID`)))
left join `match` `m` on((`rd`.`matchid` = `m`.`matchid`)))
left join `matchdetails` `md` on((`m`.`matchid` = `md`.`matchid`)))
left join `game` `g` on((`md`.`matchdetailsid` = `g`.`matchdetailsid`)))
SELECT DISTINCT g.gameid, g.pointsfor, g.pointsagainst, md.matchdetailsid, m.matchid, rd.rounddetailsid, r.roundid, s.seasonid
FROM Match AS m
INNER JOIN MatchDetails as md
ON Match.MatchId = MatchDetails.MatchId
INNER JOIN Game as g
ON MatchDetails.MatchDetailSid = MatchDetailSid
INNER JOIN RoundDetails as rd
ON Match.MatchId = RoundDetails.MatchId
INNER JOIN Round as r
ON Round.RoundId = RoundDetails.RoundId
INNER JOIN Season as s
ON Round.SeasonId = Season.SeasonId
WHERE MatchId = 1