Combining table records - mysql

So I have a DB with three tables and negligible knowledge of SQL syntax
Table 1;
person_id;
person_name;
Table 2;
thing_id;
thing_name;
Table 3;
action_id;
action name;
thing_id; (referencing thing_id in the table 2)
person1_id(referencing person_id in the Table 1);
person2_id(referencing person_id in the Table 1);
Basically, I need to combine display 1st person name, 2nd person name, action name and thing name. Could I be directed to some correct join way for this?

Use LEFT JOIN:
select
action_id,
action name,
a1.thing_name,
p1.person_name as person_name1,
p2.person_name as person_name2
from table3
left join table1 p1 on p1.person_id = table3.person1_id
left join table1 p2 on p2.person_id = table3.person2_id
left join table2 a1 on a1.thing_id = table3.thing_id

select t3.action_id,
t3.action_name,
t1.person_name,
t2.person_name
from table3 t3
inner join table2 t2 on t2.ting_id = t3.ting_id,
inner join table1 t1 on t1.person_id = t3.person1_id,
inner join table1 t2 on t2.person_id = t3.person2_id

In SQL SERVER it would be something like this, you might have to adapt it slightly for mysql.
SELECT p1.person_name AS first_person_name, p2.person_name AS second_person_name, t3.action_name, t2.thing_name
FROM
table3 t3
JOIN table1 p1
ON p1.person1_id = t3.person_id
JOIN table1 p2
ON p2.person2_id = t3.person_id
JOIN table2 t2
ON t2.thing_id = t3.thing_id

Related

SQL: full outer join (ambitious column name)

I have two table, t1 and t2.
-- t1
id name address
1 Tim A
2 Marta B
-- t2
id name address
1 Tim A
3 Katarina C
If I do t1 full outer join with t2
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
However, the result has ambitious id, name, address.
How do I rename this so that I don't have duplicate column name?
Attempt:
SELECT name, address FROM
(SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id) as derived_table;
return: ERROR- duplicate column name "name".
Ditch the * in the SELECT list.
Specify the list of expressions to be returned. And qualify all column references with either the table name, or preferably, a shorter table alias.
And assign an alias to the expression and that will be the name of the column in the resultset.
Also, the query shown is not equivalent to a FULL OUTER JOIN.
If the goal is return all rows from t1, and to also return rows from t2 where a matching row doesn't exist in t1, I'd do something like this...
SELECT t.id AS t_id
, t.name AS t_name
, t.addr AS t_addr
FROM t1 t
UNION ALL
SELECT s.id
, s.name
, s.addr
FROM t2 s
LEFT
JOIN t1 r
ON r.id = s.id
WHERE r.id IS NULL
Try fully qualifying it like
SELECT t1.id, t1.name, t1.address FROM t1

Selecting from multiple tables with LEFT JOIN

I have 3 tables
t1 (select these records)
-------------
id
offer_id
business_id
t2 (offer details)
-------------
id
offer_details
business_id
t3 (business details)
-------------
id
business_name
I need to select all records from t1 and add information from t2 and t3. Seems basic but I can't seem to be able to get it right -- must be the heat.
SELECT t2.offer_details, t3.business_name
FROM t2
LEFT JOIN t1 ON (t1.offer_id = t2.id)
LEFT JOIN t3 ON (t1.business_id = t3.id)
should be
SELECT t2.offer_details, t3.business_name
FROM t1
LEFT JOIN t1 ON (t1.offer_id = t2.id)
LEFT JOIN t3 ON (t1.business_id = t3.id)
Your lead table is t1 and the join should be based on this table
How about this
Select t2.offer_details, t3.business_name
From t1
Left Join t2 ON (t1.offer_id = t2.id)
Left Join t3 ON (t1.business_id = t3.id)
If you want all records from t1, add t1.* on your select part. Assuming that all IDs in t1 exists in the other 2 tables
SELECT
t1.*, t2.offer_details, t3.business_name
FROM
t1
JOIN t2 ON t2.id = t1.offer_id
JOIN t3 ON t3.id = t1.business_id
Modify to LEFT JOIN if the IDs in t1 may be missing in t2 or t3.

Inner join of 2 tables with the same ID

I have a table(T1) in which 2 columns(X and Y) are id's. The name's of these corresponding id's are in another table (T2) with the column name.
Suppose I was only using X then, a simple Inner join would have solved my problem in getting the name.
Such as
Select T1.somedata,T1.somedata1,T2.name from T1
Inner Join T2 ON T1.X=T2.id
But,what if I want the name's to be resolved for the T1.Y also?, which name would the Inner Join resolve it to ??
Select T1.somedata,T1.somedata1,T2.name from T1
Inner Join T2 ON T1.X=T2.id
Inner Join T2 ON T1.Y=T2.id
The above query is wrong, I know. Can I get the names of those corresponding to both T1.Xand T1.Y with an INNER Join?
-Beginner
I suggest always add aliases to tables and columns. So you will be sure which data are selected.
select
T1.somedata,
T1.somedata1,
T2X.name as XName,
T2Y.name as YName
from T1 as T1
inner join T2 as T2X on T2X.id = T1.X
inner join T2 as T2Y on T2Y.id = T1.Y
This selects both names as separate columns:
Select T1.somedata,T1.somedata1,T2a.name, T2b.name
from T1
Inner Join T2 as T2a ON T1.X=T2a.id
Inner Join T2 as T2b ON T1.Y=T2b.id
The following would generate two records in the result set:
Select T1.somedata, T1.somedata1, T2.name
from T1
Inner Join T2 ON T1.X=T2.id Or T1.Y=T2.id
you need to join table T2 twice and supply aliases on the names to avoid ambiguity.
SELECT a.*,
b.name as NameB,
c.name as NameC
FROM T1 a
INNER JOIN T2 b
ON a.x = b.id
INNER JOIN T2 c
On a.y = c.id
You need to join table T2 twice and supply aliases on the names to avoid ambiguity.
SELECT a.*,
b.name as NameB,
c.name as NameC
FROM T1 a
INNER JOIN T2 b
ON a.x = b.id
INNER JOIN T2 c
On a.y = c.id

MySQL syntax for JOIN depending on condition

What would be a syntax of the following query:
Get all columns from Table1 and JOIN Table2 if matching reference (Table1ID) exists, otherwise JOIN Table3.
Simplified DB structure is more or less as below
Table1
ID Type
1 std
Table2
ID Table1ID Title Language
1 1 Test en
Table3
ID Table1ID Title Language Flag
1 1 Other en 1
Also, I now realized that Table3 will have multiple entries that refer to single Table1.id. How to limit it to return only the latest entry (with highest id) for every result?
If you don't want an entire separate set of columns for each join, this may be what you're looking for:
SELECT *
FROM (
SELECT a.ID AS Table1ID, a.Type, b.ID, b.Title, b.Language, NULL AS Flag
FROM Table1 a
JOIN Table2 b ON a.ID = b.Table1ID
UNION ALL
SELECT a.ID, a.Type, c.ID, c.Title, c.Language, c.Flag
FROM Table1 a
LEFT JOIN Table2 b ON a.ID = b.Table1ID
JOIN Table3 c ON a.ID = c.Table1ID
JOIN (
SELECT MAX(id) AS maxid
FROM Table3
GROUP BY Table1ID
) d ON c.ID = d.maxid
WHERE b.ID IS NULL
) a
ORDER BY a.Table1ID
SQLFiddle Demo
this is one way to do it.
select table1.id, table1.type, ifnull(table2.title, table3.title)
from table1
left join table2 on table1.id = table2.table1ID
left join table3 on table1.id = table3.table1ID

What kind of MySQL join do I need?

Simple MySQL tables with matching ID values across tables:
table 1;
pid, firstname
table 2;
id, pid, property, value
Lets say there is one person entry in table 1:
pid: 1
firstname: fred
For each person there are multiple table 2 entries:
pid: 1
property: likes cats?
value: no
pid: 1
property: eye colour
value: orange
pid: 1
property: favourite food
value: sox
I want to select just two of the many table two entries, say the eye colour and favour food entries for a given person ID. What kind of outer join can achieve this?
SELECT `t1`.name
FROM `table1` AS t1
LEFT JOIN `table2` t2 ON `t1`.pid = `t2`.pid
WHERE `t1`.pid = 1
AND `t2`.property = 'eye colour'
I'm stuck here, how to get two rows from table2 and include favour food also? (Before anyone says it, no I can't change the structure of this database).
Thanks for reading.
You need to left join twice:
SELECT
t1.name
,t2a.value as eye_color
,t2b.value as fav_food
FROM table1 t1
LEFT JOIN table2 t2a ON (t1.pid = t2a.pid AND t2a.property = 'eye colour')
LEFT JOIN table2 t2b ON (t1.pid = t2b.pid AND t2b.property = 'fav food')
WHERE t1.pid = 1
How about something like:
SELECT t1.name, t2.property, t2.value
FROM table2 t2
INNER JOIN table1 t1 ON t1.pid = t2.pid
WHERE t2.pid = 1
AND t2.property IN ('eye colour','favourite food')
Or you just wanted the first two however MySQL indexed it:
SELECT t1.name, t2.property, t2.value
FROM table2 t2
INNER JOIN table1 t1 ON t1.pid = t2.pid
WHERE t2.pid = 1
LIMIT 2
There's no real reason to use a LEFT JOIN here, since there should always be an associated pid defined in table1.
How about this?
SELECT t.name, t.value, t3.value
FROM
(SELECT t1.name, t2.value, t1.pid
FROM table1 t1
LEFT JOIN table2 t2 ON t1.pid = t2.pid
WHERE t1.pid = 1
AND t2.property = 'eye colour') t
LEFT JOIN table2 t3 ON t.pid = t3.pid
WHERE t.pid = 1
AND t3.property = 'favourite food'
This will also work for people who don't have an 'eye colour' or 'favourite food' entry
If you want to do this with one query then you should use INNER JOIN but i'm not recommending this. If i were you i would select first the person then i would create another query to recieve the necessary table2 entries. Try both of my solutions you could choose the right one for you.