MySQL INNER JOIN with SubQuery (well detailed) - mysql

I'm trying to add a third INNER JOIN to a SELECT Query, where this third INNER JOIN needs to look for a value in that third Table, which value needs to be coupled with the outcome of a MAX + GROUP BY construct in the main SELECT Query. This may not be possible, I don’t know. I can't get it to work :-)
Example
TableA
User - Score
userA - 10
userB - 42
userC - 32
userB - 42
userB - 18
userD - 12
userB - 65
.
Table B
User - Color
userA - Green
userB - Yellow
userC - Blue
On these two tables I use a
SELECT
MAX(TableA.Score) AS MaxScore,
TableB.Color
FROM TableA
INNER JOIN TableB
ON TableA.User = TableB.User
GROUP BY TableA.User
The output here works nicely and is
User - MaxScore - Color
UserA - 10 - Green
UserB - 65 - Yellow
UserC - 32 - Blue
Now, I have a separate table where all the Scores get names.
TableC
Score - Name
5 - Quite Low
10 - OK
25 - Not bad
32 - Fairly good
50 - Well done
65 - Excellent
What I try to do is get a QUERY result which reads…
User - MaxScore - Name - Color
UserA - 10 - OK - Green
UserB - 65 - Excellent - Yellow
UserC - 32 - Fairly Good - Blue
My QUERY would look something like this…
SELECT
TableA.User
MAX(TableA.Score) AS MaxScore,
TableC.Name,
TableB.Color
FROM TableA
INNER JOIN TableB
ON TableA.User = TableB.User
INNER JOIN TableC
ON TableC.Score = (SELECT MAX(TableA.Score) AS MaxScore FROM Table A GROUP BY TableA.User) ThisSubQueryName
GROUP BY TableA.User
My problem is clearly with the syntax of the INNER JOIN of Table C, which INNER JOIN carries that subquery. I have no idea how to do this, or if it is even possible.
Looking forward to your wisdom.
Thanks :-)
Dutch

Try this instead:
SELECT mainQ.*, c.Name
FROM (
SELECT a.`User`, MAX(a.Score) AS MaxScore, b.Color
FROM TableA AS a
INNER JOIN TableB AS b ON a.`User` = b.`User`
GROUP BY a.`User`
) AS mainQ
INNER JOIN TableC AS c
ON mainQ.MaxScore = c.Score
Though your subquery could've worked with some modifications (involving table aliases and replacing it's GROUP BY with a WHERE), correlated subqueries are relatively expensive and often unnecessary.
Edit: Wow, after all that, I just realized I basically duplicated scaisEdge's answer's query; amazing how much a couple newlines can throw off your skimming ability.

You should use a dinamic table(t) and then the inner join on TableC
select t.User, t.MaxScore, c.Name, t.Color from (
SELECT
TableA.User as User
MAX(TableA.Score) AS MaxScore,
TableB.Color as Color
FROM TableA
INNER JOIN TableB
ON TableA.User = TableB.User
GROUP BY TableA.User
) t
INNER JOIN TableC on t.MaxScore = TableC.Score

Related

Left join table with duplicate value in the key column

For dataset a
name
height
weight
Pen
155
45
Leo
172
50
Dan
180
60
Dataset b
name
nation
age
date of birth
Pen
China
22
15/10/1998
Pen
Italy
30
19/08/1990
Pen
Italy
30
30/01/1990
NULL
Japan
27
12/09/1993
I try to use the following code to join two data:
Select * From a
JOIN b
ON a.name = b.name;
How can I change my code so that I can keep everything on the a table by joining the name column in both dataset and also shows all the null value if it exists?
Following simple join on the name field can help you with that
SELECT * FROM a LEFT JOIN b ON a.name = b.name
The traditional way is to use an outer join.
Select *
From a LEFT OUTER JOIN b ON a.name = b.name
You don't need to specify OUTER, as "LEFT JOIN" will be the same in MySQL.
Select *
From a LEFT JOIN b ON a.name = b.name
Use whichever syntax you like, although in my opinion, adding the "OUTER" makes it clear to anyone reading the SQL that it's an outer join rather than an inner join.

Select rows with Left Outer Join and condition - MySQL

PEOPLE PEOPLE_FAVS
id user_id fav_id
------ ------- ----------
1 1 1
2 1 2
3 1 5
4 2 1
5 2 2
6
I have two tables PEOPLE and PEOPLE_FAVS, I am trying to get all PEOPLE which have not favorited number '5' so it should return
PEOPLE
id
------
2
3
4
5
6
I'm trying with this query:
SELECT `people`.`id`
FROM `people`
LEFT OUTER JOIN `people_favs` ON (`people_favs`.`user_id` = `people`.`id`)
WHERE (`people_favs`.`fav_id` != 5)
GROUP BY `people`.`id`
Here is a SQL Fiddle: http://sqlfiddle.com/#!2/4102b8/3
SELECT p.*
FROM people p
LEFT
JOIN people_favs pf
ON pf.user_id = p.id
AND pf.fav_id = 5
WHERE pf.fav_id IS NULL
http://sqlfiddle.com/#!2/665b6/1
You don't actually need to use an outer join. Outer joins are often used when you want to see ALL rows from one table, regardless of their condition with another. While it would work in this case (as seen by Strawberry's example), you can use the NOT EXISTS operator to check for ids that do not have 5 as a favorite.
As far as I am aware, there is little to no performance difference, but this query is a little shorter. I also feel it is a little more logical, because you aren't really joining information. That's just a personal opinion/thought though.
Try this:
SELECT id
FROM people
WHERE NOT EXISTS(SELECT id FROM people_favs WHERE fav_id = 5 AND user_id = id);
SQLFiddle example using your data.
Did you try to simply do this:
SELECT DISTINCT `people`.`id`
FROM `people`
JOIN `people_favs` ON (`people_favs`.`user_id` = `people`.`id`)
WHERE (`people_favs`.`fav_id` <> 5)
GROUP BY `people`.`id`

How To Join in MySQL Query

I have 2 tables to be joined.
Table 1 is a master table and contains a unique set of rows.
ID DESCRIPTION
01 Alpha
02 Gamma
03 Delta
04 Beta
Table 2 is a detail table containing many rows with only some of the rows matching the master table.
ID INFO MASTER_ID
0001 abc 02
0002 def 02
0004 xyz 01
0005 mno 04
I want to JOIN the tables in order to produce the following result:
Alpha "has detail"
Gamma "has detail"
Delta "does not have detail"
Beta "has detail"
Rather than:
Alpha "has detail"
Gamma "has detail"
Gamma "has detail"
Delta "does not have detail"
Beta "has detail"
The later output is returning Gamma twice and I only want it returned once.
I tried LEFT JOIN, RIGHT JOIN, INNER JOIN and none of them produce my desired result.
Thanks for helping.
use LEFT JOIN probably you are missing something
SELECT CONCAT(a. description, IF(b.master_ID IS NOT NULL, ' has detail',' does not have detail'))
FROM table1 a
LEFT JOIN (SELECT DISTINCT master_ID FROM table2) b
ON a.ID = b.master_ID
SQLFIDDLE Demo
SQLFIDDLE Demo (with double quotes)
Maybe something like this:
SELECT
Table1.DESCRIPTION,
(
CASE
WHEN EXISTS(SELECT NULL FROM Table2 WHERE Table2.MASTER_ID=Table1.ID)
THEN 'has detail'
ELSE 'does not have detail'
END
) AS has
FROM
Table1
Just a different approach:
SELECT
table1.description,
IF((EXISTS(SELECT master_id from table2 where table2.master_id = table1.id)),
'has detail',
'does not have detail') As Status
FROM table1
SELECT a.Description, IF(b.Info, "has detail", "does not have detail") as Status
FROM Table_1 a
LEFT OUTER JOIN Table_2 b
ON a.MASTER_ID = b.MASTER_ID
GROUP BY 1,2;
If your output containts the detail part, then you have to either see both rows (as it'sa valid result) or you need to aggregate the results by selecting FIRST, MAX, etc.
If you don't need the detail values themselves, then alternative would be to do two SELECTs and use UNION:
SELECT DISTINCT Table1.Description, "does not have detail" as Comment
FROM Table1
LEFT JOIN Table2 ON (Table1.ID = MASTER_ID)
WHERE Table2.id IS NULL
UNION
SELECT DISTINCT Table1.Description, "has detail" as Comment
FROM Table1
LEFT JOIN Table2 ON (Table1.ID = MASTER_ID)
WHERE Table2.id IS NOT NULL
You can also achieve this using a groupby
SELECT a.Description, IF(count(b.id) > 0, "has detail", "does not have detail") as Status
FROM Table1 a
LEFT OUTER JOIN Table2 b
ON a.iD = b.MASTER_ID
GROUP BY a.Description ORDER BY a.Description ASC

Multiple MySQL selects

I have a query but I want to add another field to it from another table...
This is what I am using now:
SELECT *
FROM tournaments t , tournament_participants t1
WHERE t.tournament_id = t1.tournament_id
ORDER BY t1.tournament_id, t1.team_id;
This works fine, but I also want to get the team name from the team table using the team_id as part of this query...
I have no idea how to do this, can anyone help?
Simply using joins:
SELECT * FROM tournaments AS t
LEFT JOIN tournament_partecipants AS tp ON t.tournament_id = tp.tournament_id
LEFT JOIN team ON tp.team_id = team.team_id
ORDER BY tp.tournament_id, tp.team_id
I have no idea what sort of table schema you have. Following query is based on lots of assumptions. So I may be wrong to what you really need. Please take a look at it.
Query:
select p.pid, p.pname, t.id as teamID
from participants p
left join tournament tt
on p.ttnid = tt.tnid
inner join team t
on tt.tnid = t.ttid
Results:
PID PNAME TEAMID
1 john 10
2 tim 10
3 alex 20
4 ron 20
5 kate 30
Reference: SQLFIDDLE
Please let us know if you require any different solution or further clarification :)
Try This:
SELECT t.*, t1.*, t2.name
FROM tournaments t
INNER JOIN tournament_participants t1 ON t.tournament_id = t1.tournament_id
INNER JOIN teams t2 ON t1.team_id = t2.team_id
ORDER BY t1.tournament_id, t1.team_id;

mysql simple subquery problem

table user
____________________________________________
id name nickname info_id
1 john apple 11
2 paul banana 12
3 pauline melon 13
table info
_____________________________________________
id job location
11 model usa
12 engineer russia
13 seller brazil
result I want
______________________________________________
1 john apple model usa
my query
left join:
select * from user a left join info b on b.id = a.info_id where a.id=1
subquery:
select a.*, b.* from (user a, info b) where b.id = a.info_id
which is better?
SELECT a.`name`, a.`nickname`, b.`job`, b.`location`
FROM `user` AS a
LEFT JOIN `info` AS b
ON ( a.`info_id` = b.`id` )
That should be pretty efficient. Try using MySQL EXPLAIN if you are concerned (also make sure there are indexes on the ID fields):
http://dev.mysql.com/doc/refman/5.1/en/using-explain.html
UPDATE
After seeing that you are not having performance problems just yet, I would not worry about it. "Don't fix what ain't broken". If you find that it is slowing down in the future, or it is bottle-necking on that function, then worry about it.
The query I gave should be pretty efficient.