Join only for specific rows where value matches a variable - mysql

I have multiple MySQL tables containing varying numbers of columns. After joining three of the tables, I have a resulting table that's structured as follows:
+------------+------------+-----------+-------+------+
| student_id | first_name | last_name | class | rank |
+------------+------------+-----------+-------+------+
| 1 | John | Doe | 2012 | 1 |
+------------+------------+-----------+-------+------+
| 2 | Suzy | Public | 2013 | 12 |
+------------+------------+-----------+-------+------+
| 3 | Mike | Smith | 2014 | 50 |
+------------+------------+-----------+-------+------+
I also have two additional tables that aren't involved in the initial join:
interest
+-------------+------------+-----------------------+----------------+
| interest_id | student_id | employer_interest | interest_level |
+-------------+------------+-----------------------+----------------+
| 1 | 1 | Wayne Enterprises | High |
+-------------+------------+-----------------------+----------------+
| 2 | 1 | Gotham National Bank | Medium |
+-------------+------------+-----------------------+----------------+
| 3 | 2 | Wayne Enterprises | Low |
+-------------+------------+-----------------------+----------------+
| 4 | 3 | Gotham National Bank | High |
+-------------+------------+-----------------------+----------------+
offers
+----------+------------+-----------------------+
| offer_id | student_id | employer_offer |
+----------+------------+-----------------------+
| 1 | 1 | Wayne Enterprises |
+----------+------------+-----------------------+
| 2 | 1 | Gotham National Bank |
+----------+------------+-----------------------+
| 3 | 2 | Wayne Enterprises |
+----------+------------+-----------------------+
The interest and offers table won't necessarily contain a record for every student_id but at the same time contain multiple records that reference a single student_id.
For each of the latter two tables, I'd like to:
Select all rows where the employer_interest or employer_offer value is equal to $var (a variable I've set in PHP)
Join these rows to the original table
For example, if $var is set to Wayne Enterprises, I'd like the resulting table to be:
+------------+------------+-----------+-------+------+-------------------+----------------+-------------------+
| student_id | first_name | last_name | class | rank | employer_interest | interest_level | employer_offer |
+------------+------------+-----------+-------+------+-------------------+----------------+-------------------+
| 1 | John | Doe | 2012 | 1 | Wayne Enterprises | High | Wayne Enterprises |
+------------+------------+-----------+-------+------+-------------------+----------------+-------------------+
| 2 | Suzy | Public | 2013 | 12 | Wayne Enterprises | Low | Wayne Enterprises |
+------------+------------+-----------+-------+------+-------------------+----------------+-------------------+
| 3 | Mike | Smith | 2014 | 50 | NULL | NULL | NULL |
+------------+------------+-----------+-------+------+-------------------+----------------+-------------------+
Is what I'm trying to do possible using just a MySQL query? If so, how do I do it?

it sounds like you just need a LEFT JOIN to the other tables since it appears you want to see all students from the first set regardless of any job offer/interest.
If so... ensure both the "Interest" and "Offers" tables have an index where the student ID is either a single element index, or first in that of a compound index.
select STRAIGHT_JOIN
ORS.Student_ID,
ORS.First_Name,
ORS.Last_Name,
ORS.Class,
ORS.Rank,
JI.Employer_Interest,
JI.Interest,
OFR.Employer_Offer
from
OriginalResultSet ORS
LEFT JOIN Interest JI
ON ORS.Student_ID = JI.Student_ID
AND JI.Employer_Interest = YourPHPVariable
LEFT JOIN Offers OFR
on JI.Student_ID = OFR.Student_ID
AND JI.Employer_Interest = OFR.Employer_Offer
To prevent "NULL" results in the employer interest, interest and offer, you can wrap them in a Coalesce() call such as (for all three columns on left join)
COALESCE( JI.Employer_Interest, " " ) Employer_Interest

Your query should be something like this:
select
s.student_id, s.first_name, s.last_name, s.class, s.rank,
i.employer_interest, i.interest_level,
o.employer_offer
from students s
left join interest i
on i.student_id = s.student_id
and i.employer_interest = 'Wayne Enterprises'
left join offers o
on o.student_id = s.student_id
and o.employer_offer = 'Wayne Enterprises'

Related

school work delivery list mysql

I have two tables:
Table students and table of school work delivered
Students table
+--------------------------+---------------------------------+
| id | name |
+--------------------------+---------------------------------+
| 1 | ADAM |
| 2 | BRIGITTE |
| 3 | ANNE |
+--------------------------+---------------------------------+
table student works
+---------------+-------------------------+------------------+
| id_works | works | id_student |
+---------------+-------------------------+------------------+
| 1 | airplane wing | 1 |
| 2 | volcano | 2 |
| 3 | law of gravity | 1 |
| 4 | airplane wing | 3 |
| 5 | law of gravity | 1 |
+-----------------------------------------+------------------+
How do I make a SELECT for work that returns the entire list of students, indicating that the work is delivered? (IMPORTANT: list of all students)
Example
LIST FOR WORK **airplane wing**
+--------------------------+---------------------------------+
| ADAM | X |
| BRIGITTE | |
| ANNE | X |
+--------------------------+--------------------- -----------+
I have tried it with LEF JOIN and IF, but it is not the list of all the students without repeating them.
SELECT
s.name ,
w.work,
w.resid_id,
if(w.work = 'airplane wing', 'X', '') as mark
FROM students s
LEFT JOIN works w
ON s.id = w.id_student
ORDER BY s.name ASC
This will give you a list of all students
And fields id_works and works will be null for those who didn't complete the work
SELECT s.name, w.id_works, w.works
FROM students s
LEFT JOIN works w
ON (w.id_student = s.id AND w.works = 'airplane wing')
ORDER BY s.name ASC

MySQL Selecting all records from one table and their matches/NULL from another table

I have three tables. Two of them are separate irrelevant tables (students and subjects), the third (entries) is one which links them both with foreign keys (student_id and subject_id).
Here are all the tables with the records:
students:
+------------+------------+-----------+---------------------+---------------------+
| student_id | first_name | surname | email | reg_date |
+------------+------------+-----------+---------------------+---------------------+
| 1 | Emily | Jackson | emilym#gmail.com | 2012-10-14 11:14:13 |
| 2 | Daniel | ALexander | daniela#hotmail.com | 2014-08-19 08:08:23 |
| 3 | Sarah | Bell | sbell#gmail.com | 1998-07-04 13:16:32 |
| 4 | Alex | Harte | AHarte#hotmail.com | 1982-06-14 00:00:00 |
+------------+------------+-----------+---------------------+---------------------+
subjects:
+------------+--------------+------------+----------------+
| subject_id | subject_name | exam_board | level_of_entry |
+------------+--------------+------------+----------------+
| 1 | Art | CCEA | AS |
| 2 | Biology | CCEA | A |
| 3 | Computing | OCR | GCSE |
| 4 | French | CCEA | GCSE |
| 5 | Maths | OCR | AS |
| 6 | Chemistry | CCEA | GCSE |
| 7 | Physics | OCR | AS |
| 8 | RS | CCEA | GCSE |
+------------+--------------+------------+----------------+
entries:
+----------+---------------+---------------+------------+
| entry_id | student_id_fk | subject_id_fk | entry_date |
+----------+---------------+---------------+------------+
| 1 | 1 | 1 | 2012-10-15 |
| 2 | 1 | 4 | 2011-09-21 |
| 3 | 1 | 3 | 2015-08-10 |
| 4 | 2 | 6 | 1992-07-13 |
| 5 | 3 | 7 | 2013-02-12 |
| 6 | 3 | 8 | 2016-01-14 |
+----------+---------------+---------------+------------+
How would I go about selecting the names of all the students (students.first_name), and the name (subjects.subject_name) of whichever subject entries they have? What I mean is that all student names are returned, and all the subject names for their entries listed beside them, with NULL for those which don't have any entries. I also want it grouped by the first_name alphabetically.
I want the output to be something like:
first_name subject_name
--------------------------
Alex NULL
Daniel Chemistry
Emily French
Emily Computing
Sarah Physics
Sarah RS
though I'm not sure if that's entirely correct.
My guess is it's like this:
SELECT students.first_name, subjects.subject_name
FROM students
JOIN entries ON entries.student_id_fk = students.student_id
JOIN subjects ON entries.subject_id_fk = subjects.subject_id
GROUP BY students.first_name;
Really the only thing I'm not sure about is which join to use and where to put it, or if the tables need to be listed in a different order. I'm thinking it should be a left join but I'm not sure.
Help is much appreciated!
You should use left join since you want to return also row for student that has no subject assigned. Plus you want to sort the result, not group. So in the end should be like this:
SELECT students.first_name, subjects.subject_name
FROM students
LEFT JOIN entries ON entries.student_id_fk = students.student_id
LEFT JOIN subjects ON entries.subject_id_fk = subjects.subject_id
ORDER BY students.first_name;
I think this could be the query but use order by and not group by (group by is for aggregate function like count() or max() )
SELECT students.first_name, subjects.subject_name
FROM entries
LEFT JOIN students ON entries.student_id_fk = students.student_id
LEFT JOIN subjects ON entries.subject_id_fk = subjects.subject_id
ORDER BY students.first_name;
You likely want a LEFT OUTER JOIN:
select stu.first_name, sub.subject_name
from students stu
join entries e
on stu.student_id = e.student_id_fk
left outer join subjects sub
on sub.subject_id = e.subject_id_fk
order by stu.first_name;
I'm away from my PC with any SQL installed, so this is untested, but should give you what you want.
Modified my answer to replace the group by with an order by as pointed out by the others. That is the proper way to do it, unless the group is there as part of a larger query that you may have trimmed out.
Left join students table on the remaining two tables sequentially is the right choice to grab all the students first name.
To order the names order by should be used.
I have create a sql fiddle for better visualization of how to get the desired output.
Here is the link: http://sqlfiddle.com/#!9/a1c850/7
The query is
select students.student_name, subjects.subject_name
from
students
left join entries on entries.student_id=students.student_id
left join subjects on entries.subject_id=subjects.subject_id
order by students.student_name;

How to select / join some data from one mySQL innodb table to another with no duplicates and choosing the last inserted row per id

I'm new to mySQL, and I'm trying to be able to either SELECT or CREATE A VIEW with the information I want to retrieve from two tables. SQLfiddle
People Table
| people_id | username | Password | Email |
----------------------------------------------
| 1 | username1 | Password1 | Email1 |
| 2 | username2 | Password2 | Email2 |
| 3 | username3 | Password3 | Email3 |
Profile Table
| people_id | id | age | location | hobbies | about |
----------------------------------------------------------------------------------------------------------------------------
| 1 | 1 | 22 | USA | skiing, snowboarding | I am from the US and I like to snowboard |
| 2 | 2 | 45 | Canada | curling, ice skating, reading | I like to ice skate! |
| 3 | 3 | 38 | USA | tv, movies, you name it | I am from the US and I like to watch the tube |
| 2 | 4 | 45 | Canada | curling, reading | I do not like to ice skate anymore |
| 2 | 5 | 46 | Canada | bowling | Bowling is my new favorite hobby! I just turned 46! |
| 1 | 6 | 22 | Brazil | skiing, snowboarding | I am orginally from the US but I just moved to brazil|
I would like to see/retrieve the data like this :
| people_id | username | age | location | hobbies | about |
------------------------------------------------------------------------------------------------------------------------------------
| 3 | username3 | 38 | USA | tv, movies, you name it | I am from the US and I like to watch the tube |
| 2 | username2 | 46 | Canada | bowling | Bowling is my new favorite hobby! I just turned 46! |
| 1 | username1 | 22 | Brazil | skiing, snowboarding | I am orginally from the US but I just moved to brazil|
So I need to select all the people_id and username from table People and then select the people_id row from Profile where the id is the largest number for each people_id
I've tried
SELECT People.people_id, People.username, Profile.age, Profile.location, Profile.hobbies, Profile.about
FROM People
INNER JOIN Profile
ON People.people_id=Profile.people_id
Which gets me closer to what I want, but I don't want to show duplicate rows, I only want to show the last row inserted into the Profile table for each people_id.
SQLfiddle
The most efficient way to get what you want is to use a not exists condition in the where clause. This definitely takes some getting used to. What the query is going to do is to get the matching row from Profile subject to the condition that no other row has a larger id. This is a round-about way of saying "get the biggest id for each person". But, it happens to produce an efficient query plan (and this is true in most databases, not just MySQL).
SELECT p.people_id, p.username, pr.age, pr.location, pr.hobbies, pr.about
FROM People p INNER JOIN
Profile pr
ON p.people_id = pr.people_id
WHERE NOT EXISTS (SELECT 1
FROM Profile pr2
WHERE pr2.people_id = pr.people_id AND
pr2.id > pr.id
);
SELECT People.people_id, People.username, Profile.age, Profile.location, Profile.hobbies, Profile.about
FROM People
INNER JOIN (SELECT * FROM Profile ORDER BY id DESC) AS Profile
ON People.people_id=Profile.people_id
GROUP BY People.people_id
ORDER BY people_id DESC

sql query to find users with at least 2 types of accounts

I'm new to relational sql. I'm trying to figure out a query to return the names of customers who have more than one type of account.
customers:
+------------+--------------+
| cid | Name |
+------------+--------------+
| 1 | Bob |
| 2 | John |
| 3 | Jane |
+------------+--------------+
accounts:
+------------+--------------+
| aid | type |
+------------+--------------+
| 1 | Checking |
| 2 | Saving |
| 3 | CD |
+------------+--------------+
transactions:
+------------+--------------+--------------+
| tid | cid | aid |
+------------+--------------+--------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 1 | 2 |
| 4 | 2 | 3 |
| 5 | 3 | 1 |
+------------+--------------+--------------+
With these tables, the query should return Bob and John. I'm having some trouble with how to write such a query. More specifically, how do I keep count of how many accounts a customer has and how do I compare if the accounts are different without adding a new column to the table?
Okay, this seems to work in SQL Fiddle with my test data structure. Try it out with your real data structure and see if it gives you what you're looking for.
SELECT name FROM customers c WHERE EXISTS(
SELECT DISTINCT aid FROM transactions
WHERE cid = c.cid
HAVING COUNT(DISTINCT aid)>1
)

How to Query a Table with Multiple Foreign Keys and Return Actual Values

New to MySQL, so please bear with me.
I'm working on a project that collects user's degrees. Users can save 3 degrees where the type, subject matter, and school are variable. These relations are normalized for other query uses so 5 tables are involved and are shown below (all have more columns then shown, just included the relevant info). The last one, 'user_degrees' is where the keys come together.
degrees
+----+-------------------+
| id | degree_type |
+----+-------------------+
| 01 | Bachelor's Degree |
| 02 | Master's Degree |
| 03 | Ph.D. |
| 04 | J.D. |
+----+-------------------+
acad_category
+------+-----------------------------------------+
| id | acad_cat_name |
+------+-----------------------------------------+
| 0015 | Accounting |
| 0026 | Business Law |
| 0027 | Finance |
| 0028 | Hotel & Restaurant Management |
| 0029 | Human Resources |
| 0030 | Information Systems and Technology |
+------+-----------------------------------------+
institutions
+--------+--------------------------------------------+
| id | inst_name |
+--------+--------------------------------------------+
| 000001 | A T Still University of Health Sciences |
| 000002 | Abilene Christian University |
| 000003 | Abraham Baldwin Agricultural College |
+------+----------------------------------------------+
users
+----------+----------+
| id | username |
+----------+----------+
| 00000013 | Test1 |
| 00000018 | Test2 |
| 00000023 | Test3 |
+----------+----------+
user_degrees
+---------+-----------+---------+---------+
| user_id | degree_id | acad_id | inst_id |
+---------+-----------+---------+---------+
| 18 | 1 | 4 | 1 |
| 23 | 1 | 15 | 1 |
| 23 | 2 | 15 | 1 |
| 23 | 3 | 15 | 1 |
+---------+-----------+---------+---------+
How can I query 'user_degrees' to find all degrees by user x, but return the actual values of the foreign keys? Taking user Test3 as an example, I'm looking for output like so (truncated for layout's sake):
+-------------------+-------------------+-------------------+
| degree_type | acad_cat_name | inst_name |
+-------------------+-------------------+-------------------+
| Bachelor's Degree | Accounting | A T Still Uni.. |
| Master's Degree | Accounting | A T Still Uni.. |
| Ph.D. | Accounting | A T Still Uni.. |
+-------------------+-------------------+-------------------+
I'm guessing a mix of multiple joins, temp tables and subqueries are the answer but am having trouble grasping the order of things. Any insight is much appreciated, thanks for reading.
You need to join user_degrees to degrees (and the other tables referenced by user_degrees). This is the query that will give you your example output:
SELECT
ud.user_id, d.degree_type, ac.acad_cat_name, i.inst_name
FROM
user_degrees ud
INNER JOIN degrees d ON d.id = ud.degree_id
INNER JOIN acad_category ac ON ac.id = ud.acad_id
INNER JOIN institutions i ON i.id = ud.inst_id
WHERE
ud.user_id = 18
You may also want to read this article to understand different kinds of joins: http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
The only way to understand these things at your stage of learning is to actually write the queries and then modify them until you get your desired output.