MySQL : Getting the sum of multiple columns - php

This is very conflict for me let me explain to the best that I could please. This is like a 2 layers to compute. The first layer is I need to get the total A, and total B, and total C, and total D . But, to get the total A is i need to compute some columns, as well as total B, C and D . The second layer is to display and get the sum of the total A ,B, C, D. This is a bunch of tables.
For the first table.
tbl_criteria
------------------------
crit_id | criteria_name
16 | sports
17 | formal
18 | talent
19 | nothing
The tbl_criteria has a sub criteria
tbl_sub_criteria
----------------------
sub_crit_id | crit_id | sub_crit_name
22 | 16 | originality
23 | 16 | audience Impact
24 | 18 | Appeal
25 | 18 | Stage Presence
Third table the judges.
tbl_judges
------------------------
judge_id | judge_name
61 | first
62 | second
63 | third
Table of contestant lets say 2 contestant
tbl_cotestant
-----------------------------------------------
con_id | contestant_number | contestant_name |
1 | 1 | john |
2 | 2 | sy |
Last table, This is the constructed table
tbl_score
--------------------------------------------------
score_id | crit_id | sub_crit_id | judge_id | con_id | contestant_number | score
1 | 16 | 22 | 61 | 1 | 1 | 25
2 | 16 | 22 | 61 | 2 | 2 | 25
3 | 16 | 22 | 62 | 1 | 1 | 25
4 | 16 | 22 | 62 | 2 | 2 | 73
5 | 16 | 22 | 63 | 1 | 1 | 70
6 | 16 | 22 | 63 | 2 | 2 | 80
7 | 16 | 23 | 61 | 1 | 1 | 25
8 | 16 | 23 | 61 | 2 | 2 | 25
9 | 16 | 23 | 62 | 1 | 1 | 25
10 | 16 | 23 | 62 | 2 | 2 | 73
11 | 18 | 23 | 63 | 1 | 1 | 70
12 | 16 | 23 | 63 | 2 | 2 | 80
13 | 18 | 24 | 61 | 1 | 1 | 25
14 | 18 | 24 | 61 | 2 | 2 | 25
15 | 18 | 24 | 62 | 1 | 1 | 25
16 | 18 | 24 | 62 | 2 | 2 | 73
17 | 18 | 24 | 63 | 1 | 1 | 70
18 | 18 | 24 | 63 | 2 | 2 | 80
19 | 18 | 25 | 61 | 1 | 1 | 25
20 | 18 | 25 | 61 | 2 | 2 | 25
21 | 18 | 25 | 62 | 1 | 1 | 25
22 | 18 | 25 | 62 | 2 | 2 | 73
23 | 18 | 25 | 63 | 1 | 1 | 70
24 | 18 | 25 | 63 | 2 | 2 | 80
25 | 17 | null | 61 | 1 | 1 | 25
26 | 17 | null | 61 | 2 | 2 | 25
27 | 17 | null | 62 | 1 | 1 | 25
28 | 17 | null | 62 | 2 | 2 | 73
29 | 17 | null | 63 | 1 | 1 | 70
30 | 17 | null | 63 | 2 | 2 | 80
31 | 19 | null | 61 | 1 | 1 | 25
32 | 19 | null | 61 | 2 | 2 | 25
33 | 19 | null | 62 | 1 | 1 | 25
34 | 19 | null | 62 | 2 | 2 | 73
35 | 19 | null | 63 | 1 | 1 | 70
36 | 19 | null | 63 | 2 | 2 | 80
The first layer output are something like this, getting the total A, B, C ,D.
Total are should be display like
(criteria 16 has two sub-criterias 22, 23 , that means it will be x2)
con_num | contestant_name | 16_judge_61 | 16_judge_62 | 16_judge_63 | total a
1 | john | 50 | 25 | 140 | 215
2 | sy | 50 | 146 | 160 | 365
Table right above, John has got a total of 215 in Criteria number 16 (crit_id 16). As well as sy has got a total of 365 in criteria number 16.
So, i have 4 criteria in my table 16,17,18,19. This is my problem, that means i need to do query one by one to get each total output and that would be like
con_num | contestant_name | 17_judge_61 | 17_judge_62 | 17_judge_63 | total b
1 | john | 25 | 25 | 70 | 120
2 | sy | 25 | 73 | 80 | 178
(criteria 18 has a sub criteria 24,25 that means it will x2)
con_num | contestant_name | 18_judge_61 | 18_judge_62 | 18_judge_63 | total c
1 | john | 50 | 50 | 140 | 240
2 | sy | 50 | 146 | 160 | 356
con_num | contestant_name | 19_judge_61 | 19_judge_62 | 19_judge_63 | total d
1 | john | 25 | 25 | 70 | 120
2 | sy | 25 | 73 | 80 | 178
I need to do that in one query, I can do only if one by one getting total A, B C. But i need a one query that execute this kind of output. How can i achieve this output?
The total_a, b , c, d are equivalent to crit_id 16, 17, 18, 19
con_num | contestant_name | 16total_a | 17total_b | 18total_c | 19total_d | Grand_total
1 | john | 215 | 120 | 240 | 120 | 695
2 | jy | 365 | 178 | 356 | 178 | 1077
This query, I'm still learning about the logic
SELECT DISTINCT(a.contestant_number) as con_num, a.contestant_name,
//Getting first the sum of total a, Notice criteria 16 has a sub criteria 22, 23
SUM(CASE WHEN s.crit_id='16' AND s.sub_crit_id = 22 AND s.judge_id='61' THEN s.score END) as 16_judge_61,
SUM(CASE WHEN s.crit_id='16' AND s.sub_crit_id = 22 AND s.judge_id='62' THEN s.score END) as 16_judge_62,
SUM(CASE WHEN s.crit_id='16' AND s.sub_crit_id = 22 AND s.judge_id='63' THEN s.score END) as 16_judge_63,
SUM(CASE WHEN s.crit_id='16' AND s.sub_crit_id = 23 AND s.judge_id='61' THEN s.score END) as 16_judge_61,
SUM(CASE WHEN s.crit_id='16' AND s.sub_crit_id = 23 AND s.judge_id='62' THEN s.score END) as 16_judge_62,
SUM(CASE WHEN s.crit_id='16' AND s.sub_crit_id = 23 AND s.judge_id='63' THEN s.score END) as 16_judge_63,
SUM(CASE WHEN s.crit_id='16' AND s.judge_id in (61, 62, 63) THEN s.score END) as 'total a'
//Criteria 17 has no sub criteria
SUM(CASE WHEN s.crit_id='17' AND s.judge_id='61' THEN s.score END) as 16_judge_61,
SUM(CASE WHEN s.crit_id='17' AND s.judge_id='62' THEN s.score END) as 16_judge_62,
SUM(CASE WHEN s.crit_id='17' AND s.judge_id='63' THEN s.score END) as 16_judge_63,
SUM(CASE WHEN s.crit_id='17' AND s.judge_id in (61, 62, 63) THEN s.score END) as 'total b'
//And iterate again for the 2 more criteria
//
FROM tbl_score s
INNER JOIN tbl_contestant a ON s.contestant_number = a.contestant_number
INNER JOIN tbl_judges j ON j.judge_id = s.judge_id
WHERE c.gender = 'male' and c.con_id = s.con_id
GROUP BY s.contestant_number
ORDER By `Grand toal' DESC";
http://sqlfiddle.com/#!9/cfe90/1
Getting the sum of only one total
http://sqlfiddle.com/#!9/9efa5/1

Put your query in a subquery, and then add together the columns to get the grand total.
SELECT x.*, `total a` + `total b` + `total c` AS `Grand Total`
FROM (put your query here) AS x

Related

How to export report in php codeigniter where database rows are displayed as column name in excel sheet

I am trying to generate a weekly report where i want to display count of people for individual day in a week.For example i want last week report where date is 17/02/2020 to 21/02/2020.
Unit Name |17/02/2020 |18/02/2020 |19/02/2020 |20/02/2020 |21/02/2020
------------------------------------------------------------------------------
unit_1 | 21 | 56 | 78 | 09 | 05
unit_2 | 10 | 18 | 23 | 12 | 112
unit_3 | 15 | 65 | 06 | 00 | 74
unit_4 | 53 | 36 | 11 | 02 | 23
unit_5 | 75 | 25 | 22 | 23 | 00
unit_6 | 78 | 24 | 00 | 05 | 18
How can i get report in above format.
I have used $this->dbutil->csv_from_result for exporting report as excel sheet.Here i have People_table where data is entered on daily basis.In report i need to disply count of P_id for individual day of week.table structure is as below:
auto_id |unit_id | date |P_id
-----------------------------------
1 | 1 | 17/02/2020 | 100
2 | 1 | 17/02/2020 | 101
3 | 1 | 17/02/2020 | 102
4 | 3 | 18/02/2020 | 103
5 | 6 | 18/02/2020 | 104
6 | 4 | 18/02/2020 | 105
7 | 5 | 19/02/2020 | 106
8 | 5 | 19/02/2020 | 107
9 | 2 | 19/02/2020 | 108
10 | 2 | 19/02/2020 | 109
11 | 6 | 19/02/2020 | 110
12 | 4 | 19/02/2020 | 111
SELECT * FROM
(
SELECT unit_id,date
FROM table) AS ptable
PIVOT(
CONCAT(unit,'_',unit_id) FOR unit_id IN (SELECT GROUP_CONCAT(unit_id) FROM table),
date FOR date IN (SELECT GROUP_CONCAT(date) FROM table)
)

MYSQL Order By 2 rows depending on 2 other rows IDS

I am trying to create a query that allows me to select the data like shown below
organizing by the role 45 and showing its win rate in order of DESC.
For example champ_1 = 45 and champ_2 = 36 but some time its can be champ_1 = 36 and champ_2 = 45. When like this how would i make the query so that is orders the win rate for champion 45 depending on if its champ1 or champ2 and then organizing it desc.
id Role Champ_1 Champ_2 Champ_1_winrate Champ_2_winrate
---|------------|------------|-----------|-----------------|---------------
1 | 1 | 45 | 17 | 0.54 | 0.46
2 | 1 | 67 | 45 | 0.52 | 0.48
5 | 1 | 45 | 27 | 0.59 | 0.41
3 | 1 | 45 | 35 | 0.29 | 0.71
4 | 1 | 45 | 23 | 0.094 | 0.916
6 | 1 | 80 | 45 | 0.38 | 0.62
7 | 1 | 45 | 47 | 0.544 | 0.456
8 | 1 | 32 | 45 | 0.78 | 0.22
It should show the data:
id Role Champ_1 Champ_2 winrate
---|------------|------------|-----------|-----------------|
6 | 1 | 80 | 45 | 0.62 |
5 | 1 | 45 | 27 | 0.59 |
7 | 1 | 45 | 47 | 0.544 |
1 | 1 | 45 | 17 | 0.54 |
2 | 1 | 67 | 45 | 0.48 |
3 | 1 | 45 | 35 | 0.29 |
8 | 1 | 32 | 45 | 0.22 |
4 | 1 | 45 | 23 | 0.094 |
I have tried the following code and its the closest I have came for over 3 hours now, so could someone help please.
SELECT *
FROM Bronze_Matchups a
WHERE (Champ_2 = 24 AND Role = 'JUNGLE')
OR (Champ_1 = 24 AND Role = 'JUNGLE')
ORDER BY Champ_2_winrate desc, Champ_1_winrate asc
You can use UNION and ORDER BY (add desc or asc in ORDER BY clause as you need)
SELECT a.id, a.Role, a.Champ_1, a.Champ_2, a.Champ_2_winrate as winrate
FROM Bronze_Matchups a
WHERE a.Champ_2 = 24
AND a.Role = 'JUNGLE'
UNION
SELECT a.id, a.Role, a.Champ_1, a.Champ_2, a.Champ_1_winrate as winrate
FROM Bronze_Matchups a
WHERE a.Champ_1 = 24
AND a.Role = 'JUNGLE'
ORDER BY winrate
Use a case-statement in your order-by
SELECT *
FROM Bronze_Matchups a
WHERE
(Champ_2 = 24 AND Role = 'JUNGLE')
OR (Champ_1 = 24 AND Role = 'JUNGLE')
ORDER BY
CASE
WHEN Champ_2 = 24 THEN Champ_2_winrate
ELSE Champ_1_winrate
END

Ranking in MySQL

Currently I am developing a system to support a competition. In this competition there are 11 judges that give a grade to the participant. This grade is stored in a table per judge. With the following Select statement I retrieve the total score from the MySQL database (and also some inner joins to select other information from other tables).
Now I want to have ranking in this system, where also ex aequo is taken into account. I have tried several mysql solutions from this forum. But somehow the statement is always incorrect. Hopefully, someone can help me.
SELECT optreden.id, optreden.wedstrijd, optreden.jaartal,
liedje.titel, club.volledige_clubnaam,
(SELECT SUM(score.score_lied) FROM score WHERE score.optreden=optreden.id) AS score
FROM optreden
INNER JOIN liedje ON optreden.liedje=liedje.id
INNER JOIN club ON liedje.uitvoerende_club=club.id
WHERE optreden.wedstrijd="voorselectie" AND optreden.jaartal=2014
GROUP BY optreden.id
ORDER BY score_lied DESC
With this query, I get the following result:
+----+--------------+------+----------+--------------+------+
| id | Competition | Year | Title | Artist (club)| Score|
+----+--------------+------+----------+--------------+------+
| 12 | voorselectie | 2014 | Song 1 | Club 1 | 792 |
| 16 | voorselectie | 2014 | Song 2 | Club 2 | 600 |
| 10 | voorselectie | 2014 | Song 3 | Club 3 | 600 |
| 11 | voorselectie | 2014 | Song 3 | Club 3 | 500 |
| 12 | voorselectie | 2014 | Song 3 | Club 3 | 400 |
The query fetches information from the following tables:
Score: in this table the scores given by the 11 judges is stored as
line-items (result is given below);
Optreden: in this table the information from the club and the song is linked;
Club: information from the club,
such as name;
Liedje: information about the song, performed by the
club.
All the tables are linked by id's. In the result, there should come a column, with the ranking of the club.
The result from the table score is as follows:
+----+----+--------+----+
| ID | Pid| Userid | 85 |
+----+----+--------+----+
| 1 | 12 | 444 | 85 |
| 12 | 12 | 454 | 92 |
| 13 | 12 | 445 | 87 |
| 14 | 12 | 446 | 56 |
| 15 | 12 | 447 | 81 |
| 16 | 12 | 448 | 78 |
| 17 | 12 | 449 | 55 |
| 18 | 12 | 450 | 69 |
| 19 | 12 | 451 | 88 |
| 20 | 12 | 452 | 69 |
| 21 | 12 | 453 | 32 |
+----+----+--------+----+
Where the columns represent the following:
- ID: the id of the score in the table;
- Pid: the id of the performance (with this performing club and song are linked);
- Userid: the userid of the 11 judges;
- Score: the score given by each judge.
The end result should be as follows:
+----+--------------+------+----------+--------------+------+------+
| id | Competition | Year | Title | Artist (club)| Score| Rank |
+----+--------------+------+----------+--------------+------+------+
| 12 | voorselectie | 2014 | Song 1 | Club 1 | 792 | 1 |
| 16 | voorselectie | 2014 | Song 2 | Club 2 | 600 | 2 |
| 10 | voorselectie | 2014 | Song 3 | Club 3 | 600 | 2 |
| 11 | voorselectie | 2014 | Song 3 | Club 3 | 500 | 4 |
| 12 | voorselectie | 2014 | Song 3 | Club 3 | 400 | 5 |
I have tried the solution from Neville before and now again. I have rewritten the SQL statement as follows:
SELECT optreden.id, optreden.wedstrijd, optreden.jaartal,
liedje.titel, club.volledige_clubnaam,
(SELECT SUM(score.score_lied) FROM score WHERE score.optreden=optreden.id) AS score, CASE
WHEN #prev_value = score THEN #rank_count
WHEN #prev_value := score THEN #rank_count := #rank_count + 1
END AS rank,
FROM optreden
INNER JOIN liedje ON optreden.liedje=liedje.id
INNER JOIN club ON liedje.uitvoerende_club=club.id
WHERE optreden.wedstrijd="voorselectie" AND optreden.jaartal=2014
GROUP BY optreden.id
ORDER BY score_lied DESC
Here I get the error: Unknown column 'score' in 'field list'..
It seems that you are getting this error simply because there is no field score... I have extracted your inner SELECT into a JOIN so the real field can be used directly. (Not tested though, sorry)
SELECT optreden.id, optreden.wedstrijd, optreden.jaartal,
liedje.titel, club.volledige_clubnaam,
SUM(score.score_lied) AS score, CASE
WHEN #prev_value = SUM(score.score_lied) THEN #rank_count
WHEN #prev_value := SUM(score.score_lied) THEN #rank_count := #rank_count + 1
END AS rank,
FROM optreden
INNER JOIN liedje ON optreden.liedje=liedje.id
INNER JOIN club ON liedje.uitvoerende_club=club.id
LEFT JOIN score ON score.optreden=optreden.id
WHERE optreden.wedstrijd="voorselectie" AND optreden.jaartal=2014
GROUP BY optreden.id
ORDER BY score_lied DESC
Please note that you might face another little problem with this kind of ranking: Normally, when two entities end up on the same rank, the next rank is not given to the next person. Here's what I mean with an example, with two persons ranking in 3:
1, 2, 3, 3, 5
But in your code, it will give:
1, 2, 3, 3, 4
I hope this helps.
I have tried several things. However, I had forgotten to tell you one important feature I was gonna use. The ranking of the clubs should be presented through a presentation on a big screen. Therefor the MySQL code changed a little.
I have added a support table to my database. In this support table the sum of the scores is recorded with a INSERT INTO...SELECT statement.
When this insert is done. An update script is launched which makes the ranking in the table and also makes a correct calculation for ex aequo.
Here's the update statement:
SET #rank=0, #last_score = null, #tie_build_up = 0;
UPDATE ranking_voorselectie_lied
SET rank= #rank:= if(#last_score = totaal_score_lied, #rank, #rank+#tie_build_up+1),
tie_build_up= #tie_build_up:= if(#last_score = totaal_score_lied, #tie_build_up+1, 0),
last_score= #last_score:= totaal_score_lied
WHERE wedstrijd="voorselectie" AND jaar=2014
ORDER BY totaal_score_lied DESC;
This gives me the following result:
+--------------+------+----------+-------------------+------+-----+------------+
| Wedstrijd | Jaar | Optreden | totaal_score_lied | Rank | Tie | last_score |
+--------------+------+----------+-------------------+------+-----+------------+
| voorselectie | 2014 | 12 | 792 | 1 | 0 | 792 |
| voorselectie | 2014 | 16 | 82 | 2 | 0 | 82 |
| voorselectie | 2014 | 10 | 73 | 3 | 0 | 73 |
| voorselectie | 2014 | 15 | 51 | 4 | 0 | 51 |
| voorselectie | 2014 | 3 | 50 | 5 | 0 | 50 |
| voorselectie | 2014 | 11 | 42 | 6 | 0 | 42 |
| voorselectie | 2014 | 13 | 38 | 7 | 0 | 38 |
| voorselectie | 2014 | 8 | 38 | 7 | 1 | 38 |
| voorselectie | 2014 | 14 | 37 | 9 | 0 | 37 |
| voorselectie | 2014 | 5 | 35 | 10 | 0 | 35 |
| voorselectie | 2014 | 4 | 33 | 11 | 0 | 33 |
| voorselectie | 2014 | 7 | 25 | 12 | 0 | 25 |
| voorselectie | 2014 | 9 | 23 | 13 | 0 | 23 |
+--------------+------+----------+-------------------+------+-----+------------+

Symfony rank mysql database

I am actually having loads of trouble trying to obtain the rank or position of a specific row on Symfony.
Example: player table
id - name - total
1 xxxx 100
2 yyyy 200
3 www 500
When I do the following thing on the terminal, it works fine:
SELECT id, total, name, #curRank := #curRank + 1 AS rank FROM player p, (SELECT #curRank := 0) q ORDER BY total DESC
+----+-------+----------------+------+
| id | total | name | rank |
+----+-------+----------------+------+
| 19 | 1931 | guitouman | 1 |
| 2 | 1765 | lu | 2 |
| 1 | 1583 | Seyaa | 3 |
| 17 | 1532 | coucou lapinou | 4 |
| 11 | 1494 | the moine eau | 5 |
| 7 | 1446 | alien | 6 |
| 3 | 1415 | Saiyya | 7 |
| 50 | 1231 | dfdf | 8 |
| 20 | 1230 | Jrm | 9 |
| 16 | 1221 | Ragnar | 10 |
| 6 | 1182 | arachati | 11 |
| 8 | 1025 | momo | 12 |
| 10 | 789 | kingrom | 13 |
| 13 | 777 | le seur | 14 |
| 53 | 743 | aaa | 15 |
| 14 | 568 | Rakhamo | 16 |
| 9 | 466 | sapeur coco | 17 |
| 12 | 446 | chamboul | 18 |
| 51 | 321 | sdfdsf | 19 |
| 54 | 132 | | 20 |
| 52 | 46 | sdfsdf | 21 |
| 48 | 0 | dragma | 22 |
+----+-------+----------------+------+
The probleme is to get this working in Symfony2 where the "#" or "Set" keyword is not recognized. I have tried this :
$query -> $this->_em->createQuery('SET #rownum := 0;SELECT id, total, rank FROM SELECT #rownum := #rownum + 1 AS rank, id, totalTroopRecieved FROM clan ORDER BY total;')->setParameter('id', $this->getId());
return $query->getResult();
Which gives this error:
[Syntax Error] line 0, col 24: Error: Expected IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | PartialObjectExpression | "(" Subselect ")" | CaseExpression, got '#'
I feel desperate .. Spending 2 days for this when i know it works via sql queries but not on symfony makes me mad ..
I tried NUMBER_ROW() or RANK() function but it does not seem to work on Mysql.
Thank you for your precious help.

MySQL - get sum() of group

I have this table similar to MySQL - get sum() grouped max() of group
id | person | score | date | g | b | m |
-----------------------------------------------------------
1 | 32 | 444 | 2011-05 | 0 | 1 | o |
2 | 65 | 528 | 2011-05 | 1 | 0 | 1 |
3 | 77 | 455 | 2011-05 | 0 | 0 | 1 |
4 | 32 | 266 | 2011-05 | 1 | 1 | 0 |
5 | 77 | 100 | 2011-05 | 0 | 0 | 1 |
6 | 77 | 457 | 2011-05 | 1 | 0 | 0 |
7 | 77 | 457 | 2011-05 | 1 | 0 | 1 |
8 | 65 | 999 | 2011-05 | 0 | 0 | 1 |
9 | 32 | 222 | 2011-05 | 0 | 1 | 1 |
The result should be:
person | score | date | g | b | m |
-----------------------------------------------------
32 | 932 | 2012-05 | 1 | 3 | 1 |
66 | 1527 | 2012-05 | 1 | 0 | 2 |
77 | 1469 | 2012-05 | 2 | 0 | 3 |
But I couldn't achieve what I want to. I am trying to get for each person sum of its scores, g, m and b fields in each month. I'm very newbie about subqueries.
Thank you!
You can't just group by month, since the same month can appear in more than one year, so group by year as well, e.g.:
SELECT person, YEAR(`date`), MONTH(`date`),
SUM(score), SUM(b), SUM(g), SUM(m)
FROM MyTable
GROUP BY person, YEAR(`date`), MONTH(`date`)
If your date column is actually not a date type but a varchar or similar, and it contains yyyy-dd as shown, than you can just do:
SELECT person, `date`,
SUM(score), SUM(b), SUM(g), SUM(m)
FROM MyTable
GROUP BY person, `date`

Categories