Join one table rows with another table columns in mysql - mysql

I am new to mysql, Need to join two tables as below scenario
Table One : questions{question_id,question}
Example: question_id question
q01 communication skills
q02 reasoning skills
q03 technical skills
Table Two : grades{grade_id,grade}
Example : grade_id grade
gr01 below avg
gr02 avg
gr03 good
gr04 best
Want to join above two tables for below result
question_id question gr01 gr02 gr03 gr04
q01 communication skills below avg avg good best
q02 reasoning skills below avg avg good best
q03 technical skills below avg avg good best
Please help if it is possible.

You may want to have a look to same tutorial on database design. There are many good ones on the web. In the mean time, this may help you a little bit:
It seems you may need a table for 'persons' or similar such as:
TABLE persons
person_id int autoincrement primary key
person_name varchar(45)
--------
persons_attributes
Then you will have a questions table recording when the attributes of a person were taken
Table questions
question_id int autoincrement primary key
personid int
date_input date
communication_skills_id int
reasoning_skills_id int
technical_skills_id int
and you may need extra tables for: communication_skills; reasoning_skills; and technical_skill with a format as:
TABLE xxx_skills
xxx_skill_id int
grade varchar(30) #"below average", "average", "good","best"
Then you may join your tables as:
SELECT p.person_name, q.date_input, c.grade communication_skill, r.grade reasoning_skill, t.grade technical_skill
FROM questions q
INNER JOIN persons p
on q.person_id = p.person_id
INNER JOIN communication_skills c
ON q.communication_id = c.communication_id
INNER JOIN reasoning_skills r
ON q.reasoning_skills_id = reasoning_skills_id
INNER JOIN technical_skill t
ON q.technical_skills_id = t.technical_skills_id;

Related

How can I query entity belonged in 2 different values in another table?

I have a database schema like below.
What is the SQL query to find people who belong to two different teams and are coach role in one team and player role in another team?
Person
-------------
Id int
Name varchar(255)
Member
-------------
Id int
PersonId int
TeamId int
Role varchar(255)
Team
-------------
Id int
TeamName varchar(255)
What I can come up with so far is
SELECT * FROM Person p
JOIN Member m
ON p.Id = m.PersonId
GROUP BY p.Id
HAVING COUNT(m.Id) > 1;
I am not sure this is a correct approach. Can anyone please help me with this?
Thanks
The query you wrote will return any player which has more than one entry in the Member table. For example, if you had a person with a 'player' role in 3 different teams, your query will return that person. Of course, under the assumption that this case could happen.
If you want to select people which are players in AT LEAST one team and coaches in AT LEAST one team, you could use:
SELECT p.Id, p.Name
FROM Person p
WHERE EXISTS (SELECT 1 -- select anything for checking if the row exists
FROM Member m
WHERE m.PersonId = p.Id
AND m.Role LIKE 'coach')
AND EXISTS (SELECT 1
FROM Member m
WHERE m.PersonId = p.Id
AND m.Role LIKE 'player')
Note that this query assumes there are no Member entries in which person is a player and a coach on the same team. If there are such entries, query will return those people as well.
For easier role management, I would also suggest moving roles to a separate table, and using their Ids for comparison instead (m.Role = [id of the role in 'Role' table]).

Complex query on SQL database to get winner of election

I have a few tables that are set up like so:
Table past_elections:
election_ID bigint(15) unsigned;
Date date;
Race varchar(32)
Table candidates:
Candidate_ID bigint(15) unsigned;
FirstName varchar(60);
LastName varchar(60)
Table past_elections-candidates:
PastElection bigint(15);
Candidate bigint(15);
Votes int(8) unsigned
The past_elections-candidates is an intermediate table which links the Primary keys for the Candidate_ID in the candidates table with the election_ID in the past_elections table and I set it up this way because technically a candidate can be in the candidate table and run for more than one race on the same election (Think partial term limits or special elections where they also want to retain their seat for the following term) or where they run for reelection in another year. That is why I made that one-to-many relationship.
My question is, how do I make a query on the database to find all the winners of their races? What about a query to find out which people won their elections with less than X percentage of total votes? I know I'll probably have to use an aggregate function like MAX() along with an INNER JOIN and a GROUP BY but this one seems complex. I'm hoping someone has done something the same or similar before. Although I'm probably going to be told I set up my tables in the most inefficient manner possible for such a query. (Crossing my fingers.)
To get the winner for any event, you need to find the maximum votes per election and then join that back to the past_elections-candidates table to find the candidate number, then join to the candidates table to get their details:
SELECT pe.election_ID as elec,
c.FirstName,
c.LastName,
pecs.max_votes AS votes,
pecs.max_votes / pecs.total_votes AS percent
FROM past_elections pe
JOIN `past_elections-candidates` pec ON pec.PastElection = pe.election_ID
JOIN (SELECT PastElection,
MAX(Votes) AS max_votes,
SUM(Votes) AS total_votes
FROM `past_elections-candidates`
GROUP BY PastElection) pecs ON pecs.PastElection = pec.PastElection AND pecs.max_votes = pec.votes
JOIN candidates c ON c.Candidate_ID = pec.Candidate
Output:
elec FirstName LastName votes percent
1 Aladdin Arabia 200 0.5714
2 Robin Hood 150 0.4286
Demo on dbfiddle

MySQL joins and selecting from multiple tables

I am using MySQL Workbench, and I have the following question:
Using the employees data, create select queries that will provide the following information:
Show a list of employees and what department they are in
Columns: Employee Name, Department Name
I have two statements which provide the exact same return, but it's 1000 rows! Am I doing this "join" properly?
SELECT
departments.dept_name, employees.last_name, employees.first_name
FROM
departments, employees
WHERE
departments.dept_name = employees.departments.dept_name;
and
SELECT
dept_name, last_name, first_name
FROM
departments
INNER JOIN
employees
ON
departments.dept_name = employees.departments.dept_name;
Tables employees and departments are always many to many. Therefore, we need input table between them, which has columns id_emp and id_dep or more often 4 column, id_emp, id_dep, from, to. After that, your question is clear and we can speak about.
Example:
Tables:
employees emp_dep departments
id_emp first_name id id_emp id_dep id_dep name
1 John 1 1 1 1 Finacial
2 Elsa 2 2 2 2 Human res
Note: id_emp & id_dep in table emp_dep can't be together primary key beacause every employee can work many times again in same department.
Query on 3 table:
SELECT e.first_name,
d.name
FROM (employees e
INNER JOIN emp_dep ed ON e.id_emp = ed.id_emp)
INNER JOIN departments d ON ed.id_dep = d.id_dep;
Output:
first_name name
John Financial
Elsa Human res
SQL for create this database and table:
CREATE DATABASE employees_dep;
CREATE TABLE employees (id_emp INT AUTO_INCREMENT PRIMARY KEY, first_name VARCHAR(10));
CREATE TABLE departments (id_dep INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(10));
CREATE TABLE emp_dep (id int AUTO_INCREMENT PRIMARY KEY, id_emp INT, id_dep INT);
Both are correct, but the second is better.
Both are same. However second one would be faster given large volume of data, but won't matter on small sized tables.

SQL - need help writing/modifying query

I've battling with this for a few days now and as SQL is not something I use too often I can't get my query to work the way I want it to.
I have a simple test database for tagging records using "toxi" solution (three tables, one acts as a link "ProgramCourses")
My tables
Program:
- ProgramID : int
- ProgramName : varchar
Course:
- CourseID : int
- CourseName : varchar
ProgamCourses:
- ProgramID : int
- CourseID : int
What I'm trying to do is to collect all tags as string and then add them as a new column to Program table.
My query
SELECT * , GROUP_CONCAT(c.CourseName) AS tags_list
FROM `Program` p
LEFT JOIN ProgramCourses AS pc ON p.ProgramID = pc.ProgramID
LEFT JOIN Course AS c ON pc.CourseID = c.CourseID
GROUP BY p.ProgramID
ORDER BY p.ProgramID
this kinda does what I need but it duplicates some columns and result I get is:
ProgramID ProgramName ProgramID CourseID CourseID CourseName tags_list
instead of
ProgramID ProgramName CourseName
Any help would be very appreciated.
If someone is kind enough to write a query for me could you please write it with full names of tables and columns as this would make it easier for me to understand and adopt for other purposes.
Thank you.
T.
DISTINCT c.CourseName Returns a count of the number of rows with different CourseName.
SELECT * , GROUP_CONCAT(DISTINCT c.CourseName) AS tags_list
FROM `Program` p
LEFT JOIN ProgramCourses AS pc ON p.ProgramID = pc.ProgramID
LEFT JOIN Course AS c ON pc.CourseID = c.CourseID
GROUP BY p.ProgramID
ORDER BY p.ProgramID
For More Info visit it Official
Try this
SELECT * , GROUP_CONCAT(c.CourseName) AS tags_list
FROM `Program` p
LEFT JOIN ProgramCourses AS pc using(ProgramID)
LEFT JOIN Course AS c using(CourseID)
GROUP BY p.ProgramID
ORDER BY p.ProgramID

Select rows that match arbitrary criterias

I have a MySql table like this:
ID Category Value
A LOCATION COPENHAGEN
A LOCATION MADRID
B LOCATION MADRID
C LOCATION MADRID
C LOCATION AARHUS
C POSITION WEBDESIGN
D POSITION SYSADMIN
D POSITION WEBDESIGN
A GENDER MALE
B GENDER MALE
C GENDER FEMALE
Id, Category and Values together forms the key. Note that they are dynamic (user defined) and the table will be large.
Now I want to get all ID that match some criteria. To be returned, it is enough for the ID to match one value within each Category.
For example:
GIVE ME ALL IDS WHO HAVE
((LOCATION = COPENHAGEN OR LOCATION = MADRID) AND (GENDER = MALE))
should return A, B
Another example:
GIVE ME ALL IDS WHO HAVE
((POSITION = SYSADMIN OR POSITION = WEBDESIGN) AND (GENDER = FEMALE) AND (LOCATION = COPENHAGEN OR LOCATION = MADRID))
should return C
The returned ids are to be used as a subquery for another query - so performance matters.
UPDATE
I've created this sql fiddle with sample data and a proposed not working solution.
[Removed initial response as it was non-functional. In making it functional I came up with the query in the second edit which is much preferable.]
Edit
It seems like you're trying to create a schema to keep track of people working in various locations, and from your data it seems like they might hold multiple titles among various offices. The below schema would allow you to define each person, job, and location only once and then connect them using a linking table.
TABLE People
p_id INT AI PK
p_name VARCHAR
p_sex BOOL
...
TABLE Offices
o_ID INT AI PK
o_name VARCHAR
o_location VARCHAR
...
TABLE Jobs
j_ID INT AI PK
j_name VARCHAR
...
TABLE People_Jobs_Offices --linking table
p_ID INT PK
o_ID INT PK
j_ID INT PK
Now get all of the Sysadmins in Madrid or Copenhagen:
SELECT *
FROM People_Jobs_Offices pjo
INNER JOIN People p
ON pjo.p_id = p.p_id
INNER JOIN Jobs j
on pjo.j_id = j.j_id
INNER JOIN Offices o
ON pjo.o_id = o.o_id
WHERE
j.j_name = 'SYSADMIN'
AND ( o.o_location = 'MADRID'
OR o.o_location = 'COPENHAGEN' )
This approach is called Database Normalization, and generally makes the best use of indexes in any RDBMS, as well as keeping the number of rows in your tables to a minimum by avoiding the duplication of data.
Edit²
I've re-fiddled your SQLfiddle. Much of this would have to be done porgrammatically, ie. determining which categories/how many joins/table aliases/column names, but you'd want to start out with whatever table the ID column references so you have a solid starting point for these joins, I've just created the users table for illustration.
CREATE TABLE users (`ID` varchar(16),`name` varchar(16));
INSERT INTO users (`ID`, `name`)
VALUES ('A', 'andrew'), ('B', 'bob'), ('C', 'charla');
And the query:
SELECT u.*,
gen.value 'gender',
pos.value 'position',
loc.value 'location'
FROM users u
LEFT JOIN yourtable gen
ON u.ID = gen.ID
AND gen.category = 'GENDER'
LEFT JOIN yourtable pos
ON u.id = pos.id
AND pos.category = 'POSITION'
LEFT JOIN yourtable loc
ON u.id = loc.id
AND loc.category = 'LOCATION'
And the output:
ID NAME GENDER POSITION LOCATION
A andrew MALE (null) COPENHAGEN
A andrew MALE (null) MADRID
B bob MALE WEBDESIGN MADRID
B bob MALE SYSADMIN MADRID
C charla FEMALE (null) MADRID
C charla FEMALE (null) AARHUS
I would also make certain that, with the potential for many joins, you have indexes on category as well as ID, if not all 3 columns in the table.
The solution - for the moment - is to make a subquery for each category. Like this:
SELECT DISTINCT ID
FROM yourtable
WHERE ID IN
(SELECT ID from yourtable WHERE (Category = 'POSITION' AND Value = 'SYSADMIN'))
AND ID IN
(SELECT ID from yourtable WHERE (Category = 'LOCATION' AND Value = 'MADRID') OR (Category = 'LOCATION' AND Value = 'COPENHAGEN'))
Working example can be seen here at SQL Fiddle.
It is working, but I am worried about performance when I have many rows or am checking in many categories.