Show rows with SUM of two columns with subqueries and multiple JOINS - mysql

Hello I'm about to explode.. I have been trying for hours now getting this to work. I have found different solutions for others and tried to rewrite it so it fits to my script but it just wont work as it should.
With reference from Barmar to this post: Join tables with SUM issue in MYSQL
I have got a little way forward but I can't get it to print out what it should.
I have tried a lot of variant and moved around the JOINS etc. but without any luck. This is the query that gets nearest my wanted result:
SELECT
qs.statistic_ref_id,
qs.question_id,
SUM(qs.correct_count) AS count_correct,
qs2.total_count_2 AS total_count,
sr.user_id,
sr.quiz_id,
qq.title AS ny_titel,
qq.category_id,
SUBSTRING(qq.title,1,4) AS get_type_number,
pl.points
FROM pro_quiz_statistic AS qs
JOIN pro_quiz_statistic_ref sr ON sr.statistic_ref_id = qs.statistic_ref_id
JOIN pro_quiz_question qq ON qq.id = qs.question_id
JOIN user_points_log pl ON pl.quiz_id = sr.quiz_id AND pl.user_id = '$user_id'
JOIN ( SELECT
qs3.statistic_ref_id,
qs3.question_id,
SUM(qs3.correct_count + qs3.incorrect_count) AS total_count_2,
sr3.user_id,
sr3.quiz_id,
qq3.title AS ny_titel_2,
qq3.category_id,
SUBSTRING(qq3.title,1,4) AS get_type_number_2,
pl3.points
FROM pro_quiz_statistic AS qs3
JOIN pro_quiz_statistic_ref sr3 ON sr3.statistic_ref_id = qs3.statistic_ref_id
JOIN pro_quiz_question qq3 ON qq3.id = qs3.question_id
JOIN user_points_log pl3 ON pl3.quiz_id = sr3.quiz_id AND pl3.user_id = '$user_id'
WHERE sr3.user_id = '$user_id' AND
qq3.category_id = '3'
GROUP BY get_type_number_2 ORDER BY qs3.question_id
) qs2 ON qs2.statistic_ref_id = sr.statistic_ref_id
WHERE sr.user_id = '$user_id' AND
qq.category_id = '3'
GROUP BY get_type_number ORDER BY qs.question_id
You can see the outcome of this result in this picture (to the right):
whats_printing.jpg
The two first tables is pictures of the queries separately and is what it should print out. Just in one query.
I have tried with these two subqueries:
SELECT
qs.statistic_ref_id,
qs.question_id,
qs2.correct_count AS count_correct,
qs3.total_count_2 AS total_count,
sr.user_id,
sr.quiz_id,
qq.category_id,
SUBSTRING(qq.title,1,4) AS get_type_number,
pl.points
FROM pro_quiz_statistic AS qs
JOIN pro_quiz_statistic_ref sr ON sr.statistic_ref_id = qs.statistic_ref_id
JOIN pro_quiz_question qq ON qq.id = qs.question_id
JOIN user_points_log pl ON pl.quiz_id = sr.quiz_id AND pl.user_id = '$user_id'
JOIN (
SELECT
qs2.statistic_ref_id,
qs2.question_id,
SUM(qs2.correct_count) AS count_correct_2,
sr2.user_id,
sr2.quiz_id,
qq2.category_id,
SUBSTRING(qq2.title,1,4) AS get_type_number_2,
pl2.points
FROM pro_quiz_statistic AS qs2
JOIN pro_quiz_statistic_ref sr2 ON sr2.statistic_ref_id = qs2.statistic_ref_id
JOIN pro_quiz_question qq2 ON qq2.id = qs2.question_id
JOIN user_points_log pl2 ON pl2.quiz_id = sr2.quiz_id AND pl2.user_id = '$user_id'
WHERE sr2.user_id = '$user_id' AND
qq2.category_id = '3'
GROUP BY get_type_number_2
ORDER BY qs2.question_id
) qs2 ON qs2.statistic_ref_id = qs.statistic_ref_id
JOIN ( SELECT
qs3.statistic_ref_id,
qs3.question_id,
SUM(qs3.correct_count + qs3.incorrect_count) AS total_count_2,
sr3.user_id,
sr3.quiz_id,
qq3.category_id,
SUBSTRING(qq3.title,1,4) AS get_type_number_3,
pl3.points
FROM pro_quiz_statistic AS qs3
JOIN pro_quiz_statistic_ref sr3 ON sr3.statistic_ref_id = qs3.statistic_ref_id
JOIN pro_quiz_question qq3 ON qq3.id = qs3.question_id
JOIN user_points_log pl3 ON pl3.quiz_id = sr3.quiz_id AND pl3.user_id = '$user_id'
WHERE sr3.user_id = '$user_id' AND
qq3.category_id = '3'
GROUP BY get_type_number_3
ORDER BY qs3.question_id
) qs3 ON qs3.statistic_ref_id = qs.statistic_ref_id
WHERE sr.user_id = '$user_id' AND
qq.category_id = '3'
GROUP BY get_type_number
ORDER BY qs.question_id
but then it's not printing anything. This works:
SELECT
qs.statistic_ref_id,
qs.question_id,
SUM(qs.correct_count) AS count_correct,
sr.user_id,
sr.quiz_id,
qq.title AS ny_titel,
qq.category_id,
SUBSTRING(qq.title,1,4) AS get_type_number,
pl.points
FROM pro_quiz_statistic AS qs
JOIN pro_quiz_statistic_ref sr ON sr.statistic_ref_id = qs.statistic_ref_id
JOIN pro_quiz_question qq ON qq.id = qs.question_id
JOIN user_points_log pl ON pl.quiz_id = sr.quiz_id AND pl.user_id = '$user_id'
WHERE sr.user_id = '$user_id' AND
qq.category_id = '3'
GROUP BY get_type_number ORDER BY qs.question_id
And also this (if I run them separately):
SELECT
qs.statistic_ref_id,
qs.question_id,
SUM(qs.correct_count + qs.incorrect_count) AS count_correct,
sr.user_id,
sr.quiz_id,
qq.title AS ny_titel,
qq.category_id,
SUBSTRING(qq.title,1,4) AS get_type_number,
pl.points
FROM pro_quiz_statistic AS qs
JOIN pro_quiz_statistic_ref sr ON sr.statistic_ref_id = qs.statistic_ref_id
JOIN pro_quiz_question qq ON qq.id = qs.question_id
JOIN user_points_log pl ON pl.quiz_id = sr.quiz_id AND pl.user_id = '$user_id'
WHERE sr.user_id = '$user_id' AND
qq.category_id = '3'
GROUP BY get_type_number ORDER BY qs.question_id
But how can I combine those two to one query?

Related

MySQL query with multiple INNER JOIN returns duplicate entries in the result

I have the following data structure:
There are multiple tables:
I need the following return: sum of balance (sum(a.balance) as pnl) from tabposition.
However, this query returns duplicate results. Can anybody help me with this? Thanks
SET #dt_inicio := '2021-12-01';
SET #dt_fim := '2021-12-09';
select a.data, a.fund, 'CASH-USD' as ticker , 'CASH' as strategy, 'Dolar Cash' as company,
'Others' as type, 'Others' as sector,
sum(a.balance) as pnl from tabposition as a
inner join tablistaativos as c on a.ticker = c.ticker
inner join tabdiautil as d on a.data = d.data_util
inner join tabhistorynav as e on a.data = e.data
inner join tabhistorynav as f on d.data_util_ant = f.data
inner join tabprice as g on a.data = g.data
inner join tabprice as i on d.data_util_ant = i.data
inner join tabhistorynav as j on d.data_util_ant = j.data and a.fund = j.fund
inner join tabfatorx as l on a.data = l.data_pos
where a.data >= #dt_inicio and a.data <= #dt_fim and a.fund = 'TORK FUND' and a.qnt <> 0
and (c.class = 'ACCO' or c.class = 'ACCOUNTING' or c.class = 'SPAC' or c.class = 'ACOES' or
c.class = 'OPCOES' or c.class = 'FUNDO')
and e.official = 'Yes' and e.fund = 'TORK FIA' and f.official = 'Yes' and f.fund = 'TORK FIA'
and g.ticker = 'usdbrl' and i.ticker = 'usdbrl'
and l.cotista = 'TORK FIA'
group by a.data
order by a.data

Make a COUNT on JOIN tables

I have a query which I want to COUNT the rows. The problem is when I try to count the exact same query it's printing 9 but when I run the query and print the rows it's only 5 (as it should be)
Here is the query that works and show the 5 rows:
$results_quiz = $pdo->query("SELECT
sr.statistic_ref_id,
sr.quiz_id,
sr.user_id,
sr.total_time,
qm.name AS q_name,
qm.category_id,
qm.subcategory_id,
sc.sub_category_id,
sc.sub_category_name AS quiz_type,
pl.time,
pl.points,
COUNT(qs.correct_count) AS count_correct
FROM pro_quiz_statistic_ref AS sr
JOIN pro_quiz_master qm ON qm.id = sr.quiz_id
JOIN pro_quiz_subcategory sc ON sc.sub_category_id = qm.subcategory_id
JOIN user_points_log pl ON pl.quiz_id = sr.quiz_id AND pl.user_id = '$get_id'
JOIN pro_quiz_statistic qs ON qs.statistic_ref_id = sr.statistic_ref_id
WHERE
sr.user_id = '$get_id' AND
qs.correct_count = '1'
GROUP BY
sr.statistic_ref_id,
qs.correct_count
ORDER BY qm.name ASC");
The above code works like it should but when I use this:
$count_results_quiz = $pdo->query("SELECT COUNT('
sr.statistic_ref_id,
sr.quiz_id,
sr.user_id,
sr.total_time,
qm.name AS q_name,
qm.category_id,
qm.subcategory_id,
sc.sub_category_id,
sc.sub_category_name AS quiz_type,
pl.time,
pl.points,
COUNT(qs.correct_count) AS count_correct')
FROM pro_quiz_statistic_ref AS sr
JOIN pro_quiz_master qm ON qm.id = sr.quiz_id
JOIN pro_quiz_subcategory sc ON sc.sub_category_id = qm.subcategory_id
JOIN user_points_log pl ON pl.quiz_id = sr.quiz_id AND pl.user_id = '$get_id'
JOIN pro_quiz_statistic qs ON qs.statistic_ref_id = sr.statistic_ref_id
WHERE
sr.user_id = '$get_id' AND
qs.correct_count = '1'
GROUP BY
sr.statistic_ref_id,
qs.correct_count
ORDER BY qm.name ASC")->fetchColumn();
it's printing "9". Anyone knows why?
I found another solution by splitting the tables into two queries/tables. One of them showing more than 0 (at least 1) correct answer and the other one showing 0 correct answers. This way it also fits better to my needs.

specifying preferred results for GROUP BY values

I have the following (simplified) query:
SELECT
u.idnumber AS user_idnumber,
sst_status.value AS scorm_status,
sst_starttime.value AS scorm_starttime,
sst_duration.value AS scorm_duration,
sst_score.value AS scorm_score,
u.id as uid,
s.id as scormid,
ss.id as ssid
FROM {user} u
LEFT JOIN {prog_user_assignment} prua ON prua.userid = u.id
LEFT JOIN {prog} pr ON prua.programid = pr.id
LEFT JOIN {prog_courseset} prcs ON prcs.programid = pr.id
LEFT JOIN {prog_courseset_course} prcsc ON prcsc.coursesetid = prcs.id
LEFT JOIN {course} c ON prcsc.courseid = c.id
LEFT JOIN {scorm} s ON s.id = cm.instance
LEFT JOIN {scorm_scoes} ss ON ss.scorm = s.id
LEFT JOIN {scorm_scoes_track} sst_status
ON sst_status.userid = u.id
AND sst_status.scormid = ss.scorm
AND sst_status.element = 'cmi_core.lesson_status'
AND sst_status.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_starttime
ON sst_starttime.userid = u.id
AND sst_starttime.scormid = ss.scorm
AND sst_starttime.element = 'x.start.time'
AND sst_starttime.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_duration
ON sst_duration.userid = u.id
AND sst_duration.scormid = ss.scorm
AND sst_duration.element = 'cmi.core.total_time'
AND sst_duration.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_score
ON sst_score.userid = u.id
AND sst_score.scormid = ss.scorm
AND sst_score.element = 'cmi.core.score.raw'
AND sst_score.scoid = ss.id
WHERE u.id IN([SOME_EXAMPLE_IDS_HERE]) AND u.deleted = 0
group by u.idnumber, c.id
Now the problem is that without the GROUP BY clause, some of the records have values for scorm_status, scorm_starttime etc. However, these contain duplicates. But, with the group by statement, only NULL values are returned for these columns. Does anyone have a clue on how to resolve this?
Using GROUP_CONCAT and SUBSTRING_INDEX:-
SELECT
u.idnumber AS user_idnumber,
SUBSTRING_INDEX(GROUP_CONCAT(sst_status.value), ',', 1) AS scorm_status,
SUBSTRING_INDEX(GROUP_CONCAT(sst_starttime.value), ',', 1) AS scorm_starttime,
SUBSTRING_INDEX(GROUP_CONCAT(sst_duration.value), ',', 1) AS scorm_duration,
SUBSTRING_INDEX(GROUP_CONCAT(sst_score.value), ',', 1) AS scorm_score,
u.id as uid,
s.id as scormid,
ss.id as ssid
FROM {user} u
LEFT JOIN {prog_user_assignment} prua ON prua.userid = u.id
LEFT JOIN {prog} pr ON prua.programid = pr.id
LEFT JOIN {prog_courseset} prcs ON prcs.programid = pr.id
LEFT JOIN {prog_courseset_course} prcsc ON prcsc.coursesetid = prcs.id
LEFT JOIN {course} c ON prcsc.courseid = c.id
LEFT JOIN {scorm} s ON s.id = cm.instance
LEFT JOIN {scorm_scoes} ss ON ss.scorm = s.id
LEFT JOIN {scorm_scoes_track} sst_status
ON sst_status.userid = u.id
AND sst_status.scormid = ss.scorm
AND sst_status.element = 'cmi_core.lesson_status'
AND sst_status.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_starttime
ON sst_starttime.userid = u.id
AND sst_starttime.scormid = ss.scorm
AND sst_starttime.element = 'x.start.time'
AND sst_starttime.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_duration
ON sst_duration.userid = u.id
AND sst_duration.scormid = ss.scorm
AND sst_duration.element = 'cmi.core.total_time'
AND sst_duration.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_score
ON sst_score.userid = u.id
AND sst_score.scormid = ss.scorm
AND sst_score.element = 'cmi.core.score.raw'
AND sst_score.scoid = ss.id
WHERE u.id IN([SOME_EXAMPLE_IDS_HERE]) AND u.deleted = 0
group by u.idnumber, c.id
This is getting the first non null values of these fields. Note that this is relying on the fields not containing commas (but easy enough to specify a different separator for the GROUP_CONCAT). You can specify an order for the GROUP_CONCAT to get your preferred value if required.
Here is a very simplified version of your query:
select u.idnumber AS user_idnumber, sst_status.value AS scorm_status,
sst_starttime.value AS scorm_starttime, sst_duration.value AS scorm_duration,
sst_score.value AS scorm_score, u.id as uid, s.id as scormid, ss.id as ssid
. . .
group by u.idnumber, c.id;
You will notice that most of the columns in the select are not in the group by. This is using a (mis)feature of MySQL and would not generally be allowed in other databases.
What MySQL does is it chooses an abritrary value from one of the rows for the result. The idea is that this works nicely if the column is constant for the group. But, it doesn't usually work as expected in other circumstances.
If you want a non-NULL value, then you can use max() or min() to get the biggest or smallest value.
For instance:
min(sst_status.value) AS scorm_status
and so on.

Only getting one result from sub select in inner join in mysql

Hi I have run into a dilemma, I am doing this query:
SELECT GROUP_CONCAT(DISTINCT(ca.category_name) SEPARATOR ', ') AS categories, pr.promo_name, pr.add_value_text, c.contract_id, c.cmeal_plan, c.cmin_markup, c.civa, c.tax_include, c.hotel_id, hi.hname, hi.hstars, im.image_file, pl.plan_name, ra.price
FROM contracts AS c
INNER JOIN hotel_info AS hi ON hi.hotel_id = c.hotel_id AND hi.destination_id = '6460'
INNER JOIN images AS im ON im.foreign_id = hi.hotel_id
INNER JOIN meal_plan AS pl ON pl.plan_code = c.cmeal_plan AND pl.lang = '1'
INNER JOIN hotel_categories AS hc ON hc.hotel_id = hi.hotel_id
INNER JOIN categories AS ca ON ca.category_code = hc.category_code AND ca.lang = '1'
LEFT JOIN
(SELECT
r.hotel_id, AVG(r.double) AS price
FROM
rates AS r ) AS ra
ON ra.hotel_id = hi.hotel_id
LEFT JOIN promotions AS pr ON pr.hotel_id = hi.hotel_id AND FIND_IN_SET(c.contract_id, pr.contract_id) > 0 AND pr.book_start <= '2012-11-01' AND pr.book_end >= '2012-11-02' AND travel_start <= '2012-11-23' AND travel_end >= '2012-11-30' AND pr.lang = '1'
WHERE c.cstart <= '2012-11-01' AND c.cend >= '2012-11-01'
AND hi.status = '1'
AND im.type ='1'
GROUP BY hi.hotel_id
I am getting all the desired results except for the sub select query.. each hotel has a price but it is only giving me back one result and the rest are all null. Is there an error in my query? If any additional information is needed please let me know and thank you in advance for any help!
You are missing the GROUP BY in your subquery, so MySQL will only return one-value. If you want all hotel_id's then you need to GROUP BY that field:
SELECT GROUP_CONCAT(DISTINCT(ca.category_name) SEPARATOR ', ') AS categories,
pr.promo_name,
pr.add_value_text,
c.contract_id,
c.cmeal_plan,
c.cmin_markup,
c.civa,
c.tax_include,
c.hotel_id,
hi.hname,
hi.hstars,
im.image_file,
pl.plan_name,
ra.price
FROM contracts AS c
INNER JOIN hotel_info AS hi
ON hi.hotel_id = c.hotel_id
AND hi.destination_id = '6460'
INNER JOIN images AS im
ON im.foreign_id = hi.hotel_id
INNER JOIN meal_plan AS pl
ON pl.plan_code = c.cmeal_plan
AND pl.lang = '1'
INNER JOIN hotel_categories AS hc
ON hc.hotel_id = hi.hotel_id
INNER JOIN categories AS ca
ON ca.category_code = hc.category_code
AND ca.lang = '1'
LEFT JOIN
(
SELECT r.hotel_id, AVG(r.double) AS price
FROM rates AS r
GROUP BY r.hotel_id <-- add a GROUP BY hotel_id then you will get avg() for each hotel
) AS ra
ON ra.hotel_id = hi.hotel_id
LEFT JOIN promotions AS pr
ON pr.hotel_id = hi.hotel_id
AND FIND_IN_SET(c.contract_id, pr.contract_id) > 0
AND pr.book_start <= '2012-11-01'
AND pr.book_end >= '2012-11-02'
AND travel_start <= '2012-11-23'
AND travel_end >= '2012-11-30'
AND pr.lang = '1'
WHERE c.cstart <= '2012-11-01'
AND c.cend >= '2012-11-01'
AND hi.status = '1'
AND im.type ='1'
GROUP BY hi.hotel_id

Query not correct?

Can anyone see an obvious error in this query?
function getFixtureDetails($league, $date, $status)
{
global $database;
$q = "SELECT g.id, g.home_user, g.home_user2, g.away_user, g.away_user2, g.home_score, g.away_score, hteam.team AS hometeam, ateam,team AS awayteam,
huser.username AS home_username, huser2.username AS home_username2, auser.username AS away_username, auser2.username AS away_username2
FROM ".TBL_FOOT_GAMES." g
INNER JOIN ".TBL_FOOT_TEAMS." hteam ON hteam.id = g.home_team
INNER JOIN ".TBL_FOOT_TEAMS." ateam ON ateam.id = g.away_team
INNER JOIN ".TBL_USERS." huser ON huser.id = g.home_user
LEFT JOIN ".TBL_USERS." huser2 ON huser2.id = g.home_user2
INNER JOIN ".TBL_USERS." auser ON auser.id = g.away_user
LEFT JOIN ".TBL_USERS." auser2 ON auser2.id = g.away_user2
WHERE g.fixture_date = '$date' AND g.leagueid = '$league' AND (g.type = '2' OR g.type = '12' OR g.type = '22' OR g.type = '32') AND g.status = '$status'
ORDER BY g.fixture_date";
return mysql_query($q, $database->myConnection());
}
Thanks
Edit, error message...
Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource
ateam.team AS awayteam,
not
ateam,team AS awayteam,