What kind of MySQL join do I need? - mysql

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.

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

How to construct sql statement to select only if the content is available in JOIN from two tables

I have two tables as such.
t1
id name
1 foo
2 bar
t2
tid id address
1 1 foss
I can execute select satement to select id 1 from t1 from both tables.
select * from t1 inner join t2 on (t1.id = 1 and t2.id = 1)
But, what I actually want is select bar from t1, and only bar, even though it isn't present in t2.
The above tables are similar to what I have been working on my project, and resembles to the same problem.
Here is what I tried.
1. I used left join t1.id = 2 and t2.id = 2
It lists all the values from t1, which I only wanted t1.id = 2.
2.inner join could be used, but since t2.id = 2 is not present.
Therefore, it doesn’t return anything.
But I wanted something that would display data from t1 and t2 if id is present in both tables, and if not display only from table t1 of only that id.
So, if I wanted to display t1.id = 2, the answer I would expect is using
select * from t1 join .....
id name tid id address
2 bar null null null
Based on your expected result this is a simple Left Join:
select *
from t1 left join t2
on t1.id = t2.id
where t1.id = 2
Use left join to get all elements of t1 even if a element of t2 with same id not exists.
Then use null to get only t1 when t2 not exists.
At last, you can add a where filter to get a subset of t1 (ie: id = 2)
SELECT t1.*, t2.*
FROM t1
LEFT JOIN t2
ON t1.id = t2.id
WHERE t2.id IS NULL
AND t1.id = 2;

SQL query to find unreferenced records

I have two tables bound through an ID field:
table1: id, name, type
table2: id, id_table1, date, status
I have to collect all the records of the table1 that have a certain value of type field and that are not been referenced in table2 plus all the records of table1 referenced in table2 that have a certain status field value.
For the first part if I remember correctly I can use the LEFT JOIN command:
LEFT JOIN table1.name
LEFT JOIN table2
ON table2.id_table1 = table1.id
WHERE (table1.value = 'value1') AND (table2.id_table1 IS NULL);
but for the second part I'm getting lost...
I'm using MySQL 5.6 and I would like to define a View to handle this.
SELECT t1.*, t2.*
FROM table1 t1
LEFT JOIN table2 t2
ON table2.id_table1 = table1.id
WHERE (t1.type= 'value1' AND t2.id IS NULL)
OR (t2.status = 'certain status' )
I would think you could just change the WHERE to:
WHERE (table1.value = 'value1')
AND (table2.id_table1 IS NULL
OR
([the other table2 status criteria)
)
;
You can try this...
SELECT T1.*,T2.*
FROM Table1 T1
LEFT JOIN Table2 T2 ON T1.Id=T2.Id_Table1
WHERE T1.Value = 'value1' AND T2.id_table1 IS NULL
UNION
SELECT T1.*,T2.*
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.Id=T2.Id_Table1
WHERE T2.Status= 'Status Criteria'

One SQL statement for two Foreign Keys

I have two tables. The first table contains ID, First_Name and Last_Name.
The 2nd table contains two foreign key fields containing different ID's of the first table.
I want to be able to run a SQL query that gets reults of the 2nd table which then grabs the First_Name of each member based on the two different foreign keys.
How would I go about doing this?
select t2.*, t1a.firstname, t1b.firstname
from table2 t2
left join table1 t1a on t2.fk1 = t1a.id
left join table1 t1b on t2.fk2 = t1b.id
Suppose the second table has fields as such
userid, supervisorid ( both referring to the Id column of the first table )
you may write join to get the value like this
SELECT t2.*, ID, firstname, lastname FROM table 2 t2
LEFT OUTER JOIN table 1 t1 ON
t2.userid = t1.id
OR t2.supervisorid = t1.id
I think correct sql would be below one using OR condition in outer join or using union
SELECT t1.id,t1.name from table1 t1, table2 t2 WHERE t1.id1 = t2.id1
UNION
SELECT t1.id,t1.name from table1 t1, table2 t2 WHERE t1.id1 = t2.id0
SELECT t1.id, t1.name from table2 t2 LEFT OUTER JOIN table1 t2 ON t1.id = t2.id or t1.id1 = t2.id0

SQL Server - exclude data where there's no connection to second table

The example below shows the result for every Name that has a connection to Table2 (Table1 TId is PK, and TId in Table2 is the FK).
SELECT T1.Name, T1.Address
FROM Table1 AS T1
INNER JOIN Table2 AS T2
ON T1.TId = T2.TId;
I want a list of all Names from Table1 that have NO corresponding row in Table2. The other way around so to speak. How could this be done?
You need to use an Outer Join as shown below:
SELECT T1.Name, T1.Address
FROM Table1 AS T1
LEFT OUTER JOIN Table2 AS T2 ON T1.TId = T2.TId
WHERE T2.TId IS NULL