Binding results of two SQL queries by column - mysql

I have tried a lot of searching online and unable to find an answer to this. As an example, lets say I have two tables, Persons and Names with the following info (this is only for illustration and I don't have control over the DB structure)
Persons:
PID FNameID LNameID
1 100 101
2 102 103
3 100 103
...
Names:
NameID Name
100 James
101 Baker
102 Thomas
103 Walter
Is there a simple query to obtain the following result, for a given person (PID) the first and last names and then combine them to display like:
PID FName LName
1 James Baker
I looked at UNION, JOIN, nested queries, etc but couldn't figure it out. Feel like I'm missing something basic. Any help is appreciated.
Wanted to add that I am able to get each name separately and combine with PHP, but I was hoping there was a Sql way of doing it (like UNION does it for row binding)

You need two joins:
select p.pid, nf.name as fname, nl.name as lname
from persons p left join
names nf
on p.fnameid = nf.nameid left join
names nl
on p.lnameid = nl.nameid;

Try this
SELECT
p.PID, fname.Name as FName, lname.Name as LName
FROM Persons p
JOIN Name fname ON p.FNameId=fname.Id
JOIN Name lname ON p.LNameId=lname.Id
WHERE p.PID=1;
More about JOIN https://dev.mysql.com/doc/refman/8.0/en/join.html

Related

How to do a "SELECT DISTINCT" with two "INNER JOIN"?

What I'm trying to do is to GetAPersonByID by doing some inner joins from different tables.
TABLE PEOPLE
IDPerson
Name
LastName
E-mail
fk_ID_Skin
1
Example
Explanation
help#please.com
1
2
Example2
Explanation
ineed#somebody.com
2
TABLE SKINS
IDSkin
Name
1
Normal
2
Weird
TABLE PRODUCTS
IDProduct
Name
fk_skin_type
Photo
1
Oil
1
PhotoOil
2
Water
2
PhotoWater
3
Cream
2
PhotoCream
I need to know which products the CUSTOMER should use according to their SKIN TYPE
But... When I tried to do the InnerJoins (My apologies for the Spanish text in the database):
SELECT
people.IDPerson AS 'Id_person',
people.name AS 'Name',
people.lastname AS 'Lastname',
people.email AS 'E-mail',
skins.name AS 'Skin',
products.name AS 'Product',
products.photo AS 'Photo'
FROM
((people
INNER JOIN skins
ON people.fk_ID_skin = skins.IDSkin)
INNER JOIN products
ON people.fk_ID_skin = products.fk_skin_type)
WHERE IDPerson = c_id;
How can I show 'X Person' without repeating the data?
I'm using MySQL Workbench
How can I show 'X Person' without repeating the data?
It sounds like you are saying you want to see only 1 row per person? Assuming that's the case then I think what you are looking to do is GROUP BY IDPerson. Then you could use the GROUP_CONCAT function in your SELECT statement to generate a comma separated list of the values Foto, Producto, etc.

Retrieve data in a single row using group keyword in sql

Let's say I have a table tbl_marks with columns and data as below.
name id section1 section2 section3 section4 year
cherry 1 100 101 102 103 2016
cherry 1 200 201 202 203 2015
cherry 1 300 301 302 303 2014
Expected Output Format :
cherry 1 100101102103 200201202203 300301302303
I would like to have scores of all sections of one year to be concatenated and then followed by scores of another year separated by space.
So I need 5 columns in single row. (name, id, scores of year1, scores of year2, scores of year3)
Please let me know how should i update the query below. Thank you.
Query : select name, id, ??? from tbl_marks group by id;
Use GROUP_CONCAT:
SELECT name,
id,
GROUP_CONCAT(CONCAT(section1, section2, section3, section4)
ORDER BY section1 SEPARATOR ' ')
FROM yourTable
GROUP BY name, id
This answer assumes that you want three columns in your result set, the three columns being the name, id, and a CSV list of marks for that name/id group (123,456,789 in this case).
SQLFiddle (courtesy of #Luke)
The process you are looking for is called 'pivoting' and is not dynamically possible in basic SQL as it is a set-based language.
Just retrieve the rows in your business logic code and turn it into columns there.
All you need to use is group_concat() and concat() functions of MySQL, e.g.
select name, group_concat(concat(value1, value2))
from table
group by name
Here is the sample SQL Fiddle.
One way to solve this is self joins.
SELECT a.id,a.name,CONCAT(a.section1, a.section2, a.section3, a.section4) as val2015
,CONCAT(b.section1, b.section2, b.section3, b.section4) as val2016
,CONCAT(c.section1, c.section2, c.section3, c.section4) as val2017
FROM test a
LEFT JOIN test b
ON b.id=a.id
LEFT JOIN test c
ON c.id=a.id
WHERE a.year=2015 AND b.year=2016 AND c.year=2017
SQL Fiddle
Edit: Changed the query according to comments.

MYSQL, is this kind of request possible?

I have persons (table person) who have 0 or N roles (tables role and personne_role).
I want to select all the persons , with the roles they have, to have this kind of result :
PHIL COLLINS | Drummer | Singer
MIKE RUTHERFORD | Singer
ION ANDERSON | Singer
MIKE JAGGER |
CARLOS SANTANA | Guitarist
......
Each line can have 0 or N roles.
To do that, I make 2 requests
the first one to get the employees (table person)
the second one to loop all the retrieved employees and retrieve each role of them (tables role and person_role)
It works BUT in the case of there are a lot of lines, it is not very efficient.
I would like the same result in 1 request.
Is it possible ?
What are the mysql keywords I must use to do that ?
Thanks for your feedback.
dominique
You could use a JOIN with a GROUP_CONCAT, something like:
SELECT person.name, role.roles
FROM person
LEFT JOIN (
SELECT person_id, GROUP_CONCAT(DISTINCT role SEPARATOR ' | ') roles
FROM person_role
GROUP BY person_id
) role ON (person.id = role.person_id)
EDIT: the fields name are just a guess, since you didn't show us the full table schema; also, if the roles are actually in a separate tale, say joined by a role_id, you'd need to add it to the subquery.

MySQL Multiple Select Ambiguous Results

Using phpMyAdmin 5.1.44 to experiment with DML commands.
I've been following tutorials on-line.
SELECT book.b_isbn, publisher.p_name FROM 'book', 'publisher' WHERE book.b_title='DSA'
Table 1
book
b_id(PK) b_isbn b_title p_id(FK)
-----------------------------------------
1 12345 DSA 1
2 23456 SD 1
3 34567 CSP 2
Table 2
publisher
p_id(PK) p_name
--------------------
1 Fred
2 John
Expected Results
b_isbn p_name
---------------------
12345 Fred
Actual Results
b_isbn p_name
----------------------
12345 Fred
34567 John
Any ideas?
You need to tell MySQL how to join the tables together (without which it just matches every book to every publisher) - use any one of:
add AND publisher.p_id = book.p_id to your WHERE clause;
tell MySQL to join ON that condition / USING that column;
... FROM book JOIN publisher ON publisher.p_id = book.p_id WHERE ...
or
... FROM book JOIN publisher USING (p_id) WHERE ...
use a NATURAL JOIN to have MySQL guess that's what you want based on the column names.
... FROM book NATURAL JOIN publisher WHERE ...
I think you need to put the fk to the pk key in the where statement
SELECT
*
FROM
book, publisher
WHERE
book.p_id=publisher.p_id
AND book.b_title='DSA'
Or even better use JOINs:
SELECT
*
FROM
book
JOIN publisher
ON book.p_id=publisher.p_id
WHERE
book.b_title='DSA'
Or if you are not sure if there is a corresponding value then use a left join. Like this:
SELECT
*
FROM
book
LEFT JOIN publisher
ON book.p_id=publisher.p_id
WHERE
book.b_title='DSA'

find out count of comma based value in MySql

I have two tables.
Table Emp
id name
1 Ajay
2 Amol
3 Sanjay
4 Vijay
Table Sports
Sport_name Played by
Cricket ^2^,^3^,^4^
Football ^1^,^3^
Vollyball ^4^,^1^
Now I want to write a query which will give me output like
name No_of_sports_played
Ajay 2
Amol 1
Sanjay 2
Vijay 2
So what will be Mysql query for this?
I agree with the above answers/comments that you are not using a database for what a database is for, but here is how you could calculate your table from your current structure in case you have no control over that:
SELECT Emp.name, IF(Played_by IS NULL,0,COUNT(*)) as Num_Sports
FROM Emp
LEFT JOIN Sports
ON Sports.Played_by RLIKE CONCAT('[[:<:]]',Emp.id,'[[:>:]]')
GROUP BY Emp.name;
See it in action here.
UPDATE: added the IF(Played_by IS NULL,0,COUNT(*)) instead of COUNT(*). This means that if an employee doesn't play anything they'll have a 0 as their Num_Sports. See it here (I also added in those ^ characters and it still works.
What it does is joins the Emp table to the Sports table if it can find the Emp.id in the corresponding Played_by column.
For example, if we wanted to see what sports Ajay played (id=1), we could do:
SELECT *
FROM Emp, Sports
WHERE Sports.Played_by LIKE '%1%'
AND Emp.id=1;
The query I gave as my solution is basically the query above, with a GROUP BY Emp.name to perform it for each employee.
The one modification is the use of RLIKE instead of LIKE.
I use RLIKE '[[:<:]]employeeid[[:>:]]' instead of LIKE '%employeeid%. The [[:<:]] symbols just mean "make sure the employeeid you match is a whole word".
This prevents (e.g.) Emp.id 1 matching the 1 in the Played_by of 3,4,11,2.
You do not want to store your relationships in a column like that. Create this table:
CREATE TABLE player_sports (player_id INTEGER NOT NULL, sport_id INTEGER NOT NULL, PRIMARY KEY(player_id, sport_id));
This assumes you have an id column in your sports table. So now a player will have one record in player_sports for each sport they play.
Your final query will be:
SELECT p.name, COUNT(ps.player_id)
FROM players p, player_sports ps
WHERE ps.player_id = p.id
GROUP BY p.name;