Query optimization for tournament scoring tables in MySQL - php

I have two tables in a tournament-related database and I need to know the most optimized SQL query to generate the correct overall results. The results must show the total points scored, minus any penalties, and scores that are tied should be broken based on the person who reached that score first.
In the database tables, I have an event log where each score is added as teams proceed through the tournament, and I have another table which shows which team is part of which tournament.
Table "xTournamentTeam" (connects a team to a tournament)
=======================
+-----+------------+--------+--------------+
| nID | Team Name | TeamID | TournamentID |
+-----+------------+--------+--------------+
| 1 | Team A | 12 | 25 |
| 2 | Team B | 13 | 25 |
| 3 | Team C | 14 | 25 |
| 4 | Team D | 15 | 25 |
| 3 | Team A | 12 | 32 |
| 4 | Team B | 13 | 32 |
+-----+------------+--------+--------------+
Table "nEventLog" (records scoring during a tournament)
=================
+-----+---------------+---------+----------+----------------+-----------------------+
| nID | nTournamentID | nTeamID | nPoints | nPointsPenalty | nEventTime |
+-----+---------------+---------+----------+----------------|-----------------------+
| 1 | 25 | 15 | 100 | 0 | 1/24/2013 6:05:14 AM |
| 2 | 25 | 14 | 100 | 0 | 1/24/2013 6:29:55 AM |
| 3 | 25 | 14 | 100 | 25 | 1/24/2013 7:09:34 AM |
| 4 | 25 | 12 | 100 | 0 | 1/24/2013 7:12:28 AM |
| 5 | 25 | 12 | 100 | 0 | 1/24/2013 8:42:59 AM |
| 6 | 25 | 12 | 100 | 50 | 1/24/2013 8:43:36 AM |
| 7 | 25 | 14 | 100 | 0 | 1/24/2013 9:15:24 AM |
| 8 | 25 | 15 | 100 | 0 | 1/24/2013 9:15:27 AM |
| 9 | 32 | 12 | 100 | 0 | 1/28/2013 8:33:49 AM |
| 10 | 32 | 13 | 100 | 25 | 1/28/2013 2:15:12 PM |
| 11 | 32 | 12 | 100 | 10 | 1/28/2013 7:12:25 AM |
| 12 | 32 | 13 | 100 | 0 | 1/29/2013 7:18:06 AM |
+-----+---------------+---------+----------+----------------+-----------------------+
In the case of the above data, the query I need should generate the following results for Tournament #25:
+-------+------------+--------+--------------+---------------+---------------------+-----------------------------+
| nRank | Team Name | TeamID | TournamentID | nTotalPoints | nTotalPointsPenalty | nLatestEventTime |
+-------+------------+--------+--------------+---------------+---------------------+-----------------------------+
| 1 | Team A | 12 | 25 | 300 | 50 | 1/24/2013 8:43:36 AM |
| 2 | Team C | 14 | 25 | 300 | 25 | 1/24/2013 9:15:24 AM |
| 3 | Team D | 15 | 25 | 200 | 0 | 1/24/2013 9:15:27 AM |
| 4 | Team B | 13 | 25 | 0 | 0 | |
+-------+------------+--------+--------------+---------------+---------------------+-----------------------------+
For load purposes, I'm trying to avoid sub-queries at all costs since the final query should be as optimized as possible. The "nRank" column can be generated programatically... MySQL shouldn't have to return it, but I'm shoing it for reference.
The query I have that is the closest is this one, but it doesn't return "Team B" because they don't have any records in the "nEventLog" table for nTournamentID #25:
SELECT xTournamentTeam.nTeamName
, sum(nEventLog.nPoints) AS nTotalPoints
, xTournamentTeam.nTeamID
, max(nEventLog.nEventTime) AS nLatestEventTime
, sum(nEventLog.nPointsPenalty) AS nTotalPenaltyPoints
, xTournamentTeam.nTournamentID
FROM
xTournamentTeam
LEFT OUTER JOIN nEventLog
ON xTournamentTeam.nTeamID = nEventLog.nTeamID
WHERE
xTournamentTeam.nTournamentID = 33
AND nEventLog.nTournamentID = 33
GROUP BY
xTournamentTeam.nID
, xTournamentTeam.nTournamentID
ORDER BY
nTotalPoints DESC
, nLatestEventTime DESC
I'm certainly no expert in MySQL queries, and I've been working on this for two days without much success, so any help would be greatly appreciated.

I change your logic a little bit, I think it's working:
SELECT
xTournamentTeam.TeamName
, sum(nEventLog.nPoints) AS nTotalPoints
, xTournamentTeam.TeamID
, max(nEventLog.nEventTime) AS nLatestEventTime
, sum(nEventLog.nPointsPenalty) AS nTotalPenaltyPoints
, xTournamentTeam.TournamentID
FROM
xTournamentTeam
LEFT OUTER JOIN nEventLog
ON xTournamentTeam.TournamentID = nEventLog.nTournamentID AND xTournamentTeam.TeamID = nEventLog.nTeamID
WHERE
xTournamentTeam.TournamentID = 25
GROUP BY
xTournamentTeam.TeamID
, xTournamentTeam.TournamentID
, xTournamentTeam.TeamName
ORDER BY
nTotalPoints DESC
If you need, you can format nulls to represent 0 or something else.

Related

Select first greater value than the x in MySQL

I'm working on an insurance comparison platform using Codeigniter.
I have a packages table which looks like this:
+----------+--------------+------------+---------------------+-------------+
| tpckg_id | tpckg_people | tpckg_days | tpckg_policy_amount | tp_name |
+----------+--------------+------------+---------------------+-------------+
| 21 | individual | 10 | 1000 | Test25 |
| 22 | family | 7 | 2000 | Testing |
| 23 | individual | 20 | 600 | TPL Care |
| 24 | family | 10 | 1000 | TPL Care |
| 25 | individual | 15 | 650 | Travel Care |
| 26 | family | 10 | 1100 | TPL Care |
| 27 | individual | 7 | 500 | TPL Care |
| 28 | family | 7 | 1200 | Travel Care |
| 29 | family | 10 | 500 | TPL Care 2 |
| 30 | individual | 11 | 500 | TPL Care |
+----------+--------------+------------+---------------------+-------------+
Now, I'm fetching the data using this query:
$this->db->select('travel_packages.tpckg_id, travel_packages.tpckg_people, travel_packages.tpckg_days, travel_packages.tpckg_policy_amount, travel_products.tp_name');
$this->db->from('travel_packages');
$this->db->join('travel_products', 'travel_products.tp_id = travel_packages.tpckg_products_id')
$this->db->where('travel_packages.tpckg_people', 'Individual');
$this->db->where('travel_packages.tpckg_days >= 10');
$this->db->group_by('travel_packages.tpckg_policy_amount');
$this->db->order_by('travel_packages.tpckg_policy_amount', 'ASC');
As expected is returns all the records which has tpckg_people = individual and tpckg_days >= 10
like this:
+----------+--------------+------------+---------------------+-------------+
| tpckg_id | tpckg_people | tpckg_days | tpckg_policy_amount | tp_name |
+----------+--------------+------------+---------------------+-------------+
| 21 | individual | 10 | 1000 | Test25 |
| 23 | individual | 20 | 600 | TPL Care |
| 25 | individual | 15 | 650 | Travel Care |
| 30 | individual | 11 | 500 | TPL Care |
+----------+--------------+------------+---------------------+-------------+
What I want it to return is only the first greater number of days if there's no equal number than what user has entered. For example if user enters 9 for number of days and I have no package with 9 number of days it should return the first greater number of days of each product.
Like this:
+----------+--------------+------------+---------------------+-------------+
| tpckg_id | tpckg_people | tpckg_days | tpckg_policy_amount | tp_name |
+----------+--------------+------------+---------------------+-------------+
| 21 | individual | 10 | 1000 | Test25 |
| 25 | individual | 15 | 650 | Travel Care |
| 30 | individual | 11 | 500 | TPL Care |
+----------+--------------+------------+---------------------+-------------+
Any help with the query, please? Thanks in advance. :-)
Here's a raw query...
Select x.*
From travel_packages x
Join
( Select tp_name name
, tpckg_people people
, min(tpckg_days) min_days
from travel_packages
where tpckg_people = 'individual'
and tpckg_days >= 9
group
by name
, people
) y
On y.name = x.tp_name
And y.people = x.tpckg_people
And y.min_days = x.tpckg_days;

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 |
+--------------+------+----------+-------------------+------+-----+------------+

Concatenate and Count the multiple rows in single rows in mysql

I want to concatenate and count data of the same column, so I can concatenate but I can not count the repeated data.
Here's my table of data:
| ID | bills | class |
|-----|-------|-------|
| 1 | 0.5 | 2 |
| 2 | 1 | 1 |
| 3 | 0.5 | 2 |
| 5 | 1 | 3 |
| 6 | 0 | 2 |
| 7 | 0.5 | 1 |
| 8 | 1 | 2 |
| 9 | 1 | 3 |
| 10 | 0.5 | 1 |
| 11 | 0 | 2 |
| 12 | 1 | 1 |
| 13 | 0 | 3 |
| 14 | 1 | 2 |
| 15 | 0 | 1 |
| 16 | 0 | 1 |
| 17 | 0.5 | 3 |
| 18 | 0 | 3 |
| 13 | 0.5 | 3 |
Here's my sql query I'm using to concatenate data:
SELECT class AS lesson,
GROUP_CONCAT( bills ORDER BY bills ) AS bills
FROM tb_presence
GROUP BY class;
Here's my result below:
| class | bills |
|-------|------------------|
| 1 | 1,0.5,0.5,1,0,0 |
| 2 | 0.5,0,1,0,1 |
| 3 | 1,1,0,0.5,0,0.5 |
Now I would like to count the data that are equal, but continue with the same concatenation.
I want to "count" the data with the same values ​​and display concatenated (column observation and only to help understanding)
| class | bills | observation |
|-------|-------|-----------------------------|
| 1 | 2,2,2 | (2=0+0) (2=0.5+0.5) (2=1+1) |
| 2 | 2,1,2 | (2=0+0) (1=0.5) (2=1+1) |
| 3 | 2,2,2 | (2=0+0) (2=0.5+0.5) (2=1+1) |
Is this really possible?
Here is a solution (thanks to #wchiquito for the sqlfiddle) See http://sqlfiddle.com/#!2/2d2c8/1
As you can see it cannot dynamically determine the bills' values and count them. But there is a count per bill value that you want.
SELECT class AS lesson,
GROUP_CONCAT( bills ORDER BY bills ) AS bills
,SUM(IF(bills=0,1,0)) AS Count0
,SUM(IF(bills=0.5,1,0)) AS Count05
,SUM(IF(bills=1,1,0)) AS Count1
,COUNT(*) AS totalRecords
,COUNT(*)
- SUM(IF(bills=0,1,0))
- SUM(IF(bills=0.5,1,0))
- SUM(IF(bills=1,1,0))
AS Missing
FROM tb_presence GROUP BY class;
I added an extra record to show how the 'missing' column could show if you were not taking all values into consideration.
Results
| LESSON | BILLS | COUNT0 | COUNT05 | COUNT1 | TOTALRECORDS | MISSING |
|--------|-----------------------------------------|--------|---------|--------|--------------|---------|
| 1 | 0.00,0.00,0.50,0.50,1.00,1.00,1.00,4.00 | 2 | 2 | 3 | 8 | 1 |
| 2 | 0.00,0.00,0.50,0.50,1.00,1.00 | 2 | 2 | 2 | 6 | 0 |
| 3 | 0.00,0.00,0.50,0.50,1.00,1.00 | 2 | 2 | 2 | 6 | 0 |

Selecting Total value of items from 2 tables and update value of another TABLE (COMPLICATED QUERY)

My case is that I want to compute a player atk power to be used on a battle module that i made, but just wondering i have actually 2 options:
Calculate Damage Dealt from the server.(my CURRENT OPTIONS)
use PHP to calculate DAMAGE DEALT and UPDATE server DATABASE values.
pass 2 of the chara id and just calculate all in the QUERY and UPDATE all(is this possible).
Question: Can I do it in a query?(option B)
my current set-up:
1 character has 4 items and i compute the characters atk by adding all 4 of the item atk and the chara base atk in the client side. (which i think is prone to security holes)
and then update the values in the server side.
Here is my tables:
chara:
+----------+------------+----------------+-------------+------------+----------+----------+----------+-----------+-----------+
| chara_id | chara_name | chara_class_id | chara_level | chara_gold | chara_hp | chara_mp | chara_xp | chara_atk | chara_def |
+----------+------------+----------------+-------------+------------+----------+----------+----------+-----------+-----------+
| 1 | LawrenceX | 1 | 5 | 230 | -175 | 1000 | 0 | 7 | 3 |
| 3 | Viscocent | 2 | 2 | 96 | -206 | 1100 | 1700 | 5 | 5 |
| 4 | Piatos | 1 | 1 | 120 | -60 | 1000 | 0 | 7 | 3 |
| 5 | Hello | 1 | 1 | 300 | -50 | 1000 | 200 | 2 | 8 |
| 6 | Sample | 3 | 2 | 251 | -85 | 900 | 0 | 9 | 1 |
| 8 | Sampuro | 2 | 1 | 170 | 895 | 1100 | 700 | 5 | 5 |
| 12 | fail | 2 | 3 | 481 | 1100 | 1300 | 0 | 21 | 9 |
| 13 | new | 1 | 1 | 1000 | -80 | 1000 | 0 | 5 | 5 |
+----------+------------+----------------+-------------+------------+----------+----------+----------+-----------+-----------+
items:
+---------+-----------------+-----------+----------+----------+----------+---------------------------------+-------------------------------------------------+------------+
| 0 | None | 0 | 0 | 0 | 0 | pics/none.png | | 400 |
| 1 | Axe | 1 | 220 | 10 | 0 | pics/weapons/axe.png | Another lumberjack axe is another man's weapon. | 200 |
| 2 | Wooden Sword | 1 | 70 | 0 | 0 | pics/weapons/wooden-sword.png | A wooden sword, 99% made from wood | 225 |
| 3 | Dagger | 1 | 60 | 5 | 0 | pics/weapons/dagger.png | A Dagger, Cheap and Sharp | 55 |
| 4 | Bow | 1 | 120 | 1 | 0 | pics/weapons/bow.png | The basics and simplest of all bows. | 120 |
| 5 | Helmet | 4 | 0 | 50 | 0 | pics/headgears/helmet.png | iron helmet - made from an iron pot scraps. | 155 |
| 6 | Tunic | 2 | 10 | 10 | 0 | pics/armors/tunic.png | A peasants tunic. | 50 |
| 7 | Armour | 2 | 0 | 75 | 0 | pics/armors/armour.png | | 150 |
| 8 | Necklace | 3 | 25 | 15 | 0 | pics/accessories/necklace.png | | 199 |
| 9 | Studded Leather | 2 | 25 | 60 | 0 | pics/armors/studded-leather.png | | 240 |
+---------+-----------------+-----------+----------+----------+----------+---------------------------------+-------------------------------------------------+------------+
equipment:
+----------+----------+-----------+-------------+----------+---------+
| equip_id | chara_id | weapon_id | headgear_id | armor_id | ring_id |
+----------+----------+-----------+-------------+----------+---------+
| 3 | 1 | 14 | 5 | 6 | 8 |
| 5 | 3 | 4 | 5 | 6 | 8 |
| 6 | 4 | 11 | 5 | 7 | 8 |
| 7 | 5 | 12 | 5 | 6 | 8 |
| 8 | 6 | 3 | 16 | 7 | 8 |
| 10 | 8 | 15 | 5 | 7 | 8 |
| 13 | 12 | 14 | 5 | 6 | 17 |
| 40 | 13 | 3 | 5 | 7 | 8 |
+----------+----------+-----------+-------------+----------+---------+
table relationships:
1 chara = 1 equipment
1 weapon_id, armor_id, ring_id, headgear_id = 1 item (total of 4 items, headgear_id = 1 item).
I CAN GET THE EQUIPMENTS OF A CHARACTER BY USING THIS QUERY(KUDOS #JC):
SELECT i1.item_atk weapon_atk,i1.item_def weapon_def,
i2.item_atk headgear_atk,
i2.item_def headgear_def,
i3.item_atk armor_atk,
i3.item_def armor_def,
i4.item_atk ring_atk,
i4.item_def ring_def
FROM equipment e LEFT JOIN
item i1 ON e.weapon_id = i1.item_id LEFT JOIN
item i2 ON e.headgear_id = i2.item_id LEFT JOIN
item i3 ON e.armor_id = i3.item_id LEFT JOIN
item i4 ON e.ring_id = i4.item_id
WHERE e.chara_id = 1
RESULTS:
+------------+------------+--------------+--------------+-----------+-----------+----------+----------+
| weapon_atk | weapon_def | headgear_atk | headgear_def | armor_atk | armor_def | ring_atk | ring_def |
+------------+------------+--------------+--------------+-----------+-----------+----------+----------+
| 275 | 25 | 0 | 50 | 10 | 10 | 25 | 15 |
+------------+------------+--------------+--------------+-----------+-----------+----------+----------+
now i want to total the atk and def of that character equipment and return it in that query
expected results:
+------------+------------+
| total_atk | total_def |
+------------+------------+
| 310 | 100 |
+------------+------------+
this is the simplest way that I can think of.
SELECT IFNULL(W.item_atk, 0) + IFNULL(H.item_atk, 0) + IFNULL(A.item_atk, 0) + IFNULL(R.item_atk, 0) AS total_atk
, IFNULL(W.item_def, 0) + IFNULL(H.item_def, 0) + IFNULL(A.item_def, 0) + IFNULL(R.item_def, 0) AS total_def
FROM equipment E
LEFT JOIN item W ON W.item_id = E.weapon_id
LEFT JOIN item H ON H.item_id = E.headgear_id
LEFT JOIN item A ON A.item_id = E.armor_id
LEFT JOIN item R ON R.item_id = E.ring_id
WHERE E.chara_id = 1
I have renamed the aliases of tables to track them easily. And I used IFNULL in case the character has no particular equipment.
==================================================================================
Dude, I just made another query, I think this is faster than the one above. Though, I haven't tested them.
SELECT SUM(IFNULL(I.item_atk, 0)) AS total_atk
, SUM(IFNULL(I.item_def, 0)) AS total_def
FROM equipment E
LEFT JOIN item I ON I.item_id = E.weapon_id
OR I.item_id = E.headgear_id
OR I.item_id = E.armor_id
OR I.item_id = E.ring_id
WHERE E.chara_id = 1
GROUP BY E.chara_id

SELECT records WHERE rows have difference on a specific column

I have a database table campaign_data. I need to select the customer_id where in the campaign there is difference in tariff. How can i do that with MySQL query. Here is some sample data.
SQL Fiddle Schema
| CAMPAIGN_ID | CUSTOMER_ID | CAMPAIGN_NAME | TARIFF |
---------------------------------------------------------
| 1 | 1 | Richmond | 100 |
| 2 | 1 | Sutton Coldfield | 75 |
| 3 | 1 | Putney | 100 |
| 4 | 1 | Kentish Town | 100 |
| 5 | 1 | Woking | 100 |
| 6 | 2 | Chiswick | 90 |
| 7 | 2 | Ealing | 100 |
| 8 | 2 | Camden | 100 |
| 9 | 3 | Croydon | 75 |
| 10 | 3 | Croydon1 | 100 |
| 11 | 3 | Archway | 100 |
| 12 | 4 | Ealing0 | 100 |
| 13 | 4 | Ealing01 | 100 |
| 14 | 4 | Ealing02 | 100 |
| 15 | 4 | Chingford | 100 |
| 16 | 4 | chingford01 | 100 |
Now as you can see customer id 1 , and 3 has different tariffs. I want to select them and leave the customer id 4 because it has campaigns with same tariffs.
Desired Output
| CUSTOMER_ID |
---------------
| 1 |
| 2 |
| 3 |
For clearification you can see customer 1 has 5 records. If in his 5 records the tariff is same (100) i want to avoid but if the tariff is not some as 4 records have 100 and one has 75, i want to select.
SELECT customer_id, count(DISTINCT tariff) as tariffs
FROM campaign_data
GROUP BY customer_id
HAVING tariffs > 1
you looking for this maybe
SELECT customer_id
FROM campaign_data
GROUP BY customer_id
HAVING count(DISTINCT tariff) > 1
http://sqlfiddle.com/#!2/48b6e/31
select
customer_id,
tariff
from campaign_data
group by customer_id
having sum(tariff)/count(tariff) <> tariff;

Categories