Mysql Remove Duplicates on Left Join 3 Tables using id - php

I have the following tables
hobbies
+----+-------------+---------------+
| id | employeeid | hobby_name |
+----+-------------+---------------+
| 1 | 123 | cooking |
| 2 | 123 | painting |
| 3 | 124 | dancing |
+----+-------------+---------------+
nonacad_recog
+----+-------------+---------------+
| id | employeeid | recog_name |
+----+-------------+---------------+
| 1 | 123 | Award1 |
| 2 | 123 | Award2 |
| 3 | 124 | Award3 |
+----+-------------+---------------+
org_membership
+----+-------------+---------------+
| id | employeeid | recog_name |
+----+-------------+---------------+
| 1 | 123 | Boyscout |
| 2 | 124 | Girlscout |
+----+-------------+---------------+
This is the query I used:
SELECT h.hobby_name,r.recog_name,o.org_name
FROM hobbies as h
JOIN nonacad_recog as r ON (h.employeeid=r.employeeid)
JOIN org_membership as o ON (r.employeeid=o.employeeid)
WHERE h.employeeid='123'
I am getting duplicate outputs:
+----+-------------+---------------------+
| hobby_name | recog_name | org_name |
+----+-------------+---------------------+
| cooking | Award1 | Boyscout |
| cooking | Award2 | Boyscout |
| painting| Award1 | Boyscout |
| painting| Award2 | Boyscout |
+----+-------------+---------------------+
What I want as an output is like this: with no duplicates
+----+-------------+---------------------+
| hobby_name | recog_name | org_name |
+----+-------------+---------------------+
| cooking | Award1 | Boyscout |
| painting| Award2 | NULL |
+----+-------------+---------------------+
also giving a null to the other columns/rows if there is nothing to return.
I might have missed out some things.
Is this possible to achieve using mysql queries?
Any solution to this?
If I get the correct table, it will be easy for me to
mysqli_fetch assoc the results and display it on a table using PHP.

The problem is that in the desired output you want to relate rows in your tables by non-existent column, which is a row number.
You can technically do it like this
SELECT MAX(CASE WHEN source = 1 THEN name END) hobby_name,
MAX(CASE WHEN source = 2 THEN name END) recog_name,
MAX(CASE WHEN source = 3 THEN name END) org_name
FROM
(
SELECT 1 source, id, hobby_name name, #n1 := #n1 + 1 rnum
FROM hobbies CROSS JOIN (SELECT #n1 := 0) i
WHERE employeeid = 123
UNION ALL
SELECT 2 source, id, recog_name, #n2 := #n2 + 1 rnum
FROM nonacad_recog CROSS JOIN (SELECT #n2 := 0) i
WHERE employeeid = 123
UNION ALL
SELECT 3 source, id, org_name, #n3 := #n3 + 1 rnum
FROM org_membership CROSS JOIN (SELECT #n3 := 0) i
WHERE employeeid = 123
ORDER BY source, id
) q
GROUP BY rnum
Output:
| HOBBY_NAME | RECOG_NAME | ORG_NAME |
|------------|------------|----------|
| cooking | Award1 | Boyscout |
| painting | Award2 | (null) |
Here is SQLFiddle demo
Here is an alternative solution. You pack all values as delimited strings with GROUP_CONCAT()
SELECT GROUP_CONCAT(DISTINCT hobby_name ORDER BY h.id) hobby_name,
GROUP_CONCAT(DISTINCT recog_name ORDER BY r.id) recog_name,
GROUP_CONCAT(DISTINCT org_name ORDER BY o.id) org_name
FROM
(
SELECT 123 employeeid
) e LEFT JOIN hobbies h
ON e.employeeid = h.employeeid
LEFT JOIN nonacad_recog r
ON e.employeeid = r.employeeid
LEFT JOIN org_membership o
ON e.employeeid = o.employeeid;
Output:
| HOBBY_NAME | RECOG_NAME | ORG_NAME |
|------------------|---------------|----------|
| cooking,painting | Award1,Award2 | Boyscout |
Here is SQLFiddle demo
and then in your client php code easily explode() column values while iterating over the resultset and build your presentation.

I think "Limit" can work:
SELECT h.hobby_name,r.recog_name,o.org_name
FROM hobbies as h,
nonacad_recog as r,
org_membership as o
WHERE h.employeeid='123'
AND r.employeeid=o.employeeid
AND h.employeeid=r.employeeid
LIMIT 1

Related

mysql: combining columns from for tables

i have this 4 tables
table FRUIT, ID is Primary key
| ID | code | A | B |
--------------------------------------------
| 1 | a01 | apple1 | quava1 |
| 2 | a02 | apple2 | quava2 |
table FLOWER, ID is Primary key
| ID | code | C | D |
--------------------------------------------
| 1 | a01 | Rose1 | Plumer1 |
| 2 | a02 | Rose2 | Plumer2 |
table ANIMAL, ID is Primary key
| ID | code | E | F |
--------------------------------------------
| 1 | a01 | butterfly1 | cat1 |
| 2 | a02 | butterfly2 | cat2 |
table DAY, code is Primary key
| code | G |
-------------------------------------
| a01 | Monday |
| a02 | Tuesday|
i want to call and combined those 4 tables into like this
| ID | A | B | C | D | E | F | G |code |
--------------------------------------------------------------------------------
| 1 | apple1 | quava1 | Rose1 | Plumer1 |butterfly1 | cat1 |Monday |a01 |
| 2 | apple2 | quava2 | Rose2 | Plumer2 |butterfly2 | cat2 |Tuesday |a02 |
this is the code:
SELECT day*, fruit*, flower*, animal*
FROM day
LEFT JOIN fruit
ON day.code = fruit.code
LEFT JOIN flower
ON day.code = flower.code
LEFT JOIN flower
ON day.code = animal.code
ORDER BY day.code DESC;
it is said that column code is ambiguous. and cannot show the table.
i need help. how can i fix this?
I would do it in this manner, using Aliases and JOINs to join all the tables (including the animal table which you forgot), and of course not forgetting to include the periods . where needed:
SELECT fr.ID, fr.A, fr.B, fl.C, fl.D, a.E, a.F, d.G, fr.code
FROM `day` AS d
LEFT JOIN `fruit` AS fr ON d.code = fr.code
LEFT JOIN `flower` AS fl ON d.code = fl.code
LEFT JOIN `animal` AS a ON d.code = a.code
ORDER BY d.code ASC;
you forget to add . between column_name and * like day.*
Try This
SELECT `day`.*, fruit.*, flower.*, animal.*
FROM `day`
LEFT JOIN fruit
ON `day`.code = fruit.code
LEFT JOIN flower
ON `day`.code = flower.code
LEFT JOIN flower
ON `day`.code = animal.code
ORDER BY `day`.code DESC;
Beside the fact that you forgot a dot '.' between the table name and the *, thats becuase you are selecting id and code column from each table, you need to specify where are you selecting from when there is more then 1 options :
SELECT fruit.A,fruit.B, flower.C,flower.D, animal.E,animal.F,day.G,day.code
FROM day
LEFT JOIN fruit
ON day.code = fruit.code
LEFT JOIN flower
ON day.code = flower.code
LEFT JOIN animal
ON day.code = animal.code
ORDER BY day.code DESC;

MySQL - Show the highest Vote

Im having a problem from mySQL , actually i want to show the fullname of the student with the highest votes in the subject.
here's the code
$query="SELECT student_tbl.fullname, student_tbl.subject,
COUNT(student_tbl.fullname)AS rating
FROM student_tbl
INNER JOIN subject_tbl
ON student_tbl.subject= subject_tbl.subjname
GROUP BY subject ORDER BY num,
COUNT(fullname) DESC";
student_tbl subject_tbl
| fullname | subject| | subjname | num |
==================== ================
| John | Math | | Math | 1 |
| Rey | Math | | Science | 2 |
| Wey | Science | | English | 3 |
| Xin | Science | =================
| Nick | English |
| Mi | English |
| John | Math |
| Xin | Science |
| Mi | English |
======================
Here's the output to my codes:
| fullname | Subject | Votes |
============================
| John | Math | 2 |
| Wey | Science | 2 |
| Nick | English | 2 |
And This is the output i want:
| fullname | Subject | Votes |
============================
| John | Math | 2 |
| Xin | Science | 2 |
| Mi | English | 2 |
SELECT s1.fullname, s1.subject, COUNT(s1.fullname) AS rating
FROM student_tbl s1
INNER JOIN subject_tbl s2
ON s1.subject= s2.subjname
GROUP BY subject, fullname
HAVING COUNT(fullname) = (
SELECT COUNT(fullname) FROM student_tbl
WHERE s1.subject = subject
GROUP BY fullname
ORDER BY COUNT(fullname) DESC
LIMIT 1
)
ORDER BY num, COUNT(fullname) DESC
SqlFiddle : http://sqlfiddle.com/#!2/aea20
I highly suggest you to use numeric keys and not string keys.
Not pretty but it works. I grouped the votes first and then got the rank.
SQL FIDDLE DEMO
SELECT fullname, subject, votes
FROM (SELECT fullname,subject,votes,
(CASE subject WHEN #curtype THEN #currow := #currow + 1
ELSE #currow := 1 AND #curtype := subject end ) + 1 AS rank
FROM (SELECT fullname,subject,Count(1) AS Votes
FROM student_tbl
GROUP BY fullname,subject) a,(SELECT #currow := 0, #curtype := '') r
ORDER BY subject,votes DESC) b
WHERE rank = 1

I want to display same column twice with different values mysql

select * from Teams;
| team_name | team_id |
| India | 1 |
| England | 2 |
| Germany | 3 |
| Japan | 4 |
select * from Matches;
| match_id | match_date | hometeam | awayteam | homescore | awayscore |
| 1 | 2014-06-24 | 1 | 2 | 3 | 0 |
| 2 | 2014-06-25 | 3 | 4 | 0 | 2 |
Matches-table hometeam and awayteam are foreign keys for Teams-table team_id
I want a select that displays the homescore and awayscore along with team_names
You have to join matches table with teams table like this:
SELECT th.team_name as team_home, m.homescore, ta.team_name as team_away, m.awayscore
FROM matches m
INNER JOIN teams th ON m.hometeam = th.team_id
INNER JOIN teams ta ON m.awayteam = ta.team_id
Here is SqlFiddle
Another one, with entire match data in one select...
select
m.*,
home.team_name as hometeam_name,
away.team_name as awayteam_name
from
matches m,
teams home,
teams away
where
home.team_id = m.hometeam
and
away.team_id = m.awayteam
;
see SQLFIDDLE

Can't get my head around GROUP_CONCAT

I cannot seem to get an GROUP_CONCAT query to work.
I have this tables, which I joined:
stud
id | stud_name |
-----------------
1 | Class1 |
2 | Class2 |
note
id | stud_id | mat_id | Note |
------------------------------------------------
1 | 1 | 1 | 10 |
2 | 1 | 2 | 9 |
3 | 1 | 1 | 10 |
mat
id | mat_name |
----------------
1 | Porc |
2 | Vaca |
Here is what I did to join them.
SELECT
`stud`.`id`
, `mat`.`mat_name`
, `note`.`note`
FROM
`stud`
LEFT JOIN
`note`
ON
(`stud`.`id` = `note`.`id_stud`)
LEFT JOIN
`mat`
ON
(`note`.`id_mate` = `mat`.`id`)
Here is what I want them to look.
mat.id | mat_name | Note |
-----------------------------
1 | Porc | 10,10 |
2 | Vaca | 9 |
Here is how they look.
mat.id | mat_name | Note |
-----------------------------
1 | Porc | 10 |
2 | Vaca | 9 |
1 | Port | 10 |
I tried doing this.
SELECT
`mat`.`mat_name`,
GROUP_CONCAT(`note`.`note`) AS `note`.`note`,
FROM ( "Here is what I did to join them." )attr_groups
GROUP BY `mat`.`mat_name`;
ORDER BY `mat`.`mat_name`;
Any ideas?
EDIT: If I add group by or ORDER by, no results are found. If I don't add them, the query works but its not concatenating them.
SELECT mat.id,
mat.mat_name,
GROUP_CONCAT(note.note) as note
FROM mat
LEFT JOIN note ON mat.id = note.mat_id
LEFT JOIN stud ON note.stud_id = stud.id
GROUP BY mat.id, mat.mat_name
ORDER BY mat.mat_name
SQLFiddle demo
You have error in group by.
GROUP BY `mat`.`mat_name`;
------------------------^^^---
remove ; from query
SELECT
`stud`.`id`
, `mat`.`mat_name`
, GROUP_CONCAT(`note`.`note`) AS Note
FROM
`stud`
LEFT JOIN
`note`
ON
(`stud`.`id` = `note`.`id_stud`)
LEFT JOIN
`mat`
ON
(`note`.`id_mate` = `mat`.`id`)
GROUP BY
`stud`.mat_id
ORDER BY
`mat`.`mat_name`
Try this:
SELECT
m.id,
m.mat_name,
GROUP_CONCAT(n.Note) as grades
FROM
mat m
LEFT JOIN note n
ON n.mat_id = m.id
GROUP BY
m.id

MYSQL SELECT rank of user (more than x & less than y)

I'm a bit stuck with a php/Mysql Query. I got 2 tables :
table_users table_ranks
---------------- ------------------------
| id | points | | name | points_needed |
---------------- ------------------------
| 1 | 2 | | lvl0 | 0 |
| 2 | 10 | | lvl1 | 10 |
| 3 | 21 | | lvl2 | 20 |
| 4 | 29 | | lvl3 | 30 |
---------------- ------------------------
I need an ouput like this :
User_1 = lvl0 (because user has 2 points)
User_2 = lvl1 (because user has just reached 10 points)
...
User_4 = lvl2 (because user has not yet reached 30 points)
Think you :)
Regards.
You can do it like this
SELECT
tu.id,
tr.name,
tu.points
FROM table_ranks as tr
LEFT JOIN (SELECT * FROM table_ranks LIMIT 1,69596585953484) as l
ON l.points_needed = (SELECT MIN(points_needed) FROM table_ranks WHERE points_needed > tr.points_needed limit 1)
LEFT OUTER JOIN table_users AS tu ON tu.points >= tr.points_needed AND tu.points < l.points_needed
WHERE tu.id IS NOT NULL
group by tu.id
Fiddle
Output
-------------------------
| id | points | name |
-------------------------
| 1 | lvl0 | 2 |
| 2 | lvl1 | 10 |
| 3 | lvl2 | 21 |
| 4 | lvl2 | 29 |
-------------------------
give this a try, a little bit messy due to table design,
SELECT u.*, r.name
FROM table_users u
INNER JOIN
(
SELECT x.name,
x.points_needed start_point,
COALESCE(y.points_needed - 1, 2000000) end_point
FROM
(
SELECT name, points_needed, #rank:=#rank+1 ranks
FROM table_ranks a, (SELECT #rank:=0) b
ORDER BY points_needed
) x
LEFT JOIN
(
SELECT name, points_needed, #rank1:=#rank1+1 ranks
FROM table_ranks a, (SELECT #rank1:=0) b
ORDER BY points_needed
) y ON x.ranks+1 = y.ranks
) r ON u.points BETWEEN r.start_point AND r.end_point
SQLFiddle Demo

Categories