Doing a join on 3 tables - mysql

I have 3 sql tables
1) a table with headers of a coupon - id of this equals the id of the second table
2) a tables with details of the coupon - user_id on this tables equals user id of the third table
3) a table with details of user
So far I have this query
"SELECT kpn_processed_deals.kpn_id,
kpn_processed_deals.purchased_date, kpn_processed_deals.claim,
kpn_processed_deals.uid,kpn_deal_headers.kpn_type,
kpn_deal_headers.title,kpn_deal_headers.created_by
FROM kpn_processed_deals INNER JOIN kpn_deal_headers ON
kpn_processed_deals.kpn_id = kpn_deal_headers.kpn_id AND
kpn_deal_headers.created_by = '$var'";
This works just fine but I want to get the value of the users email on the third table using a join but I have been unsuccessful so far. Sorry if my formatting is messy. I'm horrible at these things.

Just add another JOIN.
"SELECT p.kpn_id, p.purchased_date, p.claim, p.uid,h.kpn_type, h.title, h.created_by, u.email
FROM kpn_processed_deals AS p INNER
JOIN kpn_deal_headers AS h ON p.kpn_id = h.kpn_id
JOIN kpn_deal_users AS u ON u.user_id = p.user_id
WHERE h.created_by = '$var'";
Also notice the use of table aliases, so you don't have to repeat the verbose table names throughout the query.
And constraints on single tables should normally be in the WHERE clause; the ON clause is for conditions related to joining the tables (an exception is in outer joins, where constraints on the child table need to be in the ON clause as well).

Related

Inserting specific fields into a mysql table

I have 4 tables in a mysql db. A joining table, Author table, Output Table, and a Person table. I had to import a csv file that had an outputID and personID but only have access to the author names column, so i've added an auto increment primary key to the author table.
I want the query I've made to insert the author Id's into the joining table where the specific author related to the ID matches the specific outputID.
The following query keeps inserting the author Id's but all at the bottom of the the joining table, without any matching output id
INSERT INTO output(a_fk)
SELECT a.Author_ID
FROM authors a
INNER JOIN wholecsv w ON a.Author_Names = w.a_Author
INNER JOIN outputlist ot ON ot.Output_ID = w.a_ID
INNER JOIN output o ON o.Output_ID = ot.Output_ID
The following query keeps inserting the author Id's but all at the bottom of the the joining table, without any matching output id
That's what INSERT does : adding new records to the table.
It looks like you are actually looking for an UPDATE query. For this, you need to adjust the JOIN logic so it goes from output to authors, like :
UPDATE output o
INNER JOIN outputlist ot ON o.Output_ID = ot.Output_ID
INNER JOIN wholecsv ON ot.Output_ID = w.a_ID
INNER JOIN authors ON a.Author_Names = w.a_Author
SET o.a_fk = a.Author_ID

Updated rows not expected values with JOIN?

I've created several tables in a test database based on columns/rows in my main database.
test.websites.url = main.websites.url
test.category_main = main.websites.category1
test.category_01 = main.websites.category2
test.category_02 = main.websites.category3
etc...
The test database columns already contain all the rows from the main
database, but I need to add the rows from the respective tables to the
category_to_website table and create foreign keys because there is
currently no relation between them in the test database. That is why I have joined the
main database in the query.
When trying to use the main table as a reference for updating the existing rows in the test database, some values are updated but they are not always correct. I'm executing the query from the test database.
My query:
UPDATE category_to_website
LEFT JOIN main.websites
ON websites.url = main.websites.url
LEFT JOIN category_01
ON category_01.name = main.websites.category2
SET category_to_website.category_01_id = category_01.id
WHERE category_to_website.category_01_id = main.websites.category2
My database schema:
I suspect that the issue is with the type of JOINs I am doing, but I've tried LEFT JOIN, JOIN, and INNER JOIN and get the same results. I think that maybe I need a SELECT sub query or my WHERE clause is off?
EDIT
Based on the comments I was able to get this all sorted out. Here are the steps I took.
1. Merged the category_* tables into a category table.
2. Joined the test.websites table into the query.
UPDATE test.category_to_website
LEFT JOIN test.websites
ON test.websites.id = category_to_website.url_id
RIGHT JOIN main.websites
ON test.websites.url = main.websites.url
INNER JOIN test.category
ON test.category.name = main.websites.category1
SET category_to_website.category01_id = category.id
WHERE category_to_website.url_id = test.websites.id
UPDATE category_to_website
JOIN websites
ON websites.id = category_to_website.url_id
JOIN main.websites
ON websites.url = main.websites.url
JOIN category
ON category.name = main.websites.category1
SET category_to_website.category01_id = category.id
SETs are done to rows that participate in the JOINs. But if you LEFT JOIN to category_to_website then all its rows participate so then you must restrict them in a WHERE the way you already did in the ON.
Thank goodness you have started to relationalize that horrible schema. Keep going: replace all multiple categery_ columns in each table by just one category column for id or name. And if you named them category_id and category_name their nature would be clear. (Maybe post your next version as a new question.)

SQL - WHERE clause with JOIN

mysql_query("SELECT a.about,a.user,b.user,b.title,b.article,b.description
FROM about a
JOIN articles b ON b.user_id=a.user_id
WHERE MATCH(b.title,b.article) AGAINST ('$search')
");
I need to expand this query to include something like " AND user='$user'" but where both 'a' and 'b' tables are checked.
I could do "AND a.user='$user' AND b.user='$user'" but I will be adding 18 more tables so this is looking a bit bloated.
Is there any way to make things more compact?
You should only need to check the username on one table not both as the INNER JOIN using the user_id has already matched them up.
To be honest table b shouldn't really have a user field, instead it should just have the user_id field (this is considered normalised).
An INNER JOIN will then only return data where there is a match in both tables. So joining Table a.user_id to Table b.user_id ensures they both have a matching user_id.

Conditional JOIN determines table based on INSTR of main table field

Slightly unusual requirement here, which unfortunately is down to a poor table design a long way back down the development path!
I have 3 tables, repairs, staff, technicians
The repairs table contains all the information on repair tasks booked in to my system. This contains a field "Technician" this field will contain the ID of either a staff member (from the table staff) or an ID of an outsourced (offsite) technician (from the table technicians), in this latter case the ID will have a prefix of "T"
So, due to this latter case prefix, I need to be able to grab that T and use it to determine whether my SQL query needs to JOIN table staff or table technicians
So, I have a fairly simple SQL Query:
SELECT technicians.screenName,
repairs.turnAround, repairs.technician, repairs.dateIn, repairs.Type,
invoices.status, invoices.grossTotal
FROM repairs
LEFT JOIN invoices ON repairs.invNo=invoices.id
LEFT JOIN technicians ON technicians.id = REPLACE(repairs.technician, 'T','')
WHERE repairs.id ='REQUIRED JOB ID' ORDER BY repairs.dateIn DESC
This will work fine, and overcomes the "T" prefix for all cases where I have an outsourced technician.
BUT...
The IDs will mix up if I try to JOIN the staff table.
So I need a conditional join, such as:
LEFT JOIN
WHEN instr(repairs.technican,'T') > 0 THEN
JOIN TECHNICIANS TABLE
ELSE
JOIN STAFF TABLE
END
The further issue I can see here is that the field technicans.screenName being included in the field list will not work if I am not joining the technicians table, however, as the staff table includes a field screenName which I'd need if I joined that table, if I had an ambiguous field name screenName with no table prefix it should work shouldn't it?
EDIT: I should probably add that the conditional join example above does NOT work!
You can join both tables with including/excluding INSTR condition, and show not null value then:
SELECT COALESCE(technicians.screenName, staff.screenName) AS screenName,
repairs.turnAround, repairs.technician, repairs.dateIn, repairs.Type,
invoices.status, invoices.grossTotal
FROM repairs
LEFT JOIN invoices ON repairs.invNo=invoices.id
LEFT JOIN technicians ON instr(repairs.technican,'T') > 0 AND technicians.id = REPLACE(repairs.technician, 'T','')
LEFT JOIN staff ON instr(repairs.technican,'T') = 0 AND staff.id = repairs.technician
WHERE repairs.id ='REQUIRED JOB ID' ORDER BY repairs.dateIn DESC

MySQL Left Join With Three Tables

I have a query that requires what I think is a complicated JOIN. I have three tables that are sort of "children" of each other. The top table is "clan_members". The next is "roster_members" which gets the clan_member id. The bottom one is "match_players" which gets the roster_members id. I wrote a loop that takes me through all of the results in the clan_members table. What I want to do is find out how many matches that clan member has played in. Here's the layouts of the three tables:
[clan_members]
-id
- member_id
-join_date
[roster_members]
- id
- clan_member_id
- title
[match_players]
- id
- roster_member_id
- match_id
I have never done a JOIN with three different tables before and I have no idea what order to do them in. I would greatly appreciate it if someone could write me a query!
This query will get you the number of matches that clan member with id 123 has participated in:
select count(*) as match_count
from clan_members c, roster_members r, match_players m
where c.member_id = r.clan_member_id
and r.id = m.roster_member_id
and c.id = 123
On a side note, it would be good practice to name your columns consistently. For example, all columns that have the clan_member_id should be named the same. In the clan_members table its called id but in the roster_members table its called clan_member_id. Just makes it easier to understand how the tables join together.
SELECT DISTINCT match_id
FROM clan_members
INNER JOIN roster_members
ON clan_members.id = roster_members.clan_member_id
INNER JOIN match_players
ON roster_members.id = match_players.roster_member_id;
will get you the # of unique match_ids when all three tables are joined.