Create View by Left join on multiple columns with OR - mysql

I am trying to create a view from two tables by left joining on two columns: t1.recipient_email = t2.username or t1.created_by = t2.id. As shown in pseudocode below, I want the first t2.name to be the recipient_name and second t2.name to be sender_name. I can't think of the correct way to achieve this.
CREATE VIEW emailsent_log_view
(id_email_que_log, date_sent, recipent_email, recipient_name, send_status, sender_name)
AS
SELECT
t1.id,
t1.date_send,
t1.recipient_email,
t2.name, --recipient_name: corresponds with t1.recipient_email = t2.username
t1.send_status,
t2.name --sender_name: correspond with t1.created_by = t2.id
FROM email_que_log AS t1
LEFT JOIN user_account as t2
ON t1.recipient_email = t2.username
OR t1.created_by = t2.id

As you guessed, you can't pick and choose which row joins to which row with an or condition like that. The way to solve such issues is to join the table twice, once for each need:
CREATE VIEW emailsent_log_view
(id_email_que_log, date_sent, recipent_email, recipient_name, send_status, sender_name)
AS
SELECT
eql.id,
eql.date_send,
eql.recipient_email,
res.name AS reciever, -- From the first join
eql.send_status,
snd.name AS sender -- From the second join
FROM
email_que_log AS eql
LEFT JOIN
user_account AS res ON eql.recipient_email = res.username
LEFT JOIN
user_account AS snd ON eql.created_by = snd.id

Related

Update several select in MySQL

It's a sample to see the result.
Hello Everyone,
I wrote a query as a sample and I used several selects because I needed to add columns separately.
So, I got the result.
now I want to know if can I use an update statement for this query?
select T3.*,ao_00b950_aoproject_value.VALUE ODP from
(select T2.*,ao_00b950_aoproject_value.VALUE SOD from
(select T1.*,ao_00b950_aoproject_value.VALUE Platform from (SELECT project.LEAD,project.id,project.pname,project.pkey,ao_00b950_aoproject_value.VALUE Status FROM jira820db.project
LEFT JOIN jira820db.ao_00b950_aoproject_value
on project.ID=ao_00b950_aoproject_value.PROJECT_ID
and ao_00b950_aoproject_value.FIELD_ID =1) as T1
left join ao_00b950_aoproject_value
on T1.ID = ao_00b950_aoproject_value.project_ID
and ao_00b950_aoproject_value.field_ID=26) as T2
left join ao_00b950_aoproject_value
on T2.ID = ao_00b950_aoproject_value.project_ID
and ao_00b950_aoproject_value.field_ID=28) as T3
left join ao_00b950_aoproject_value
on T3.ID = ao_00b950_aoproject_value.project_ID
and ao_00b950_aoproject_value.field_ID=27
So, I wrote this update statement:
update
(select T3.*,ao_00b950_aoproject_value.VALUE ODP from
(select T2.*,ao_00b950_aoproject_value.VALUE SOD from
(select T1.*,ao_00b950_aoproject_value.VALUE Platform from (SELECT project.LEAD,project.id,project.pname,project.pkey,ao_00b950_aoproject_value.VALUE Status FROM jira820db.project
LEFT JOIN jira820db.ao_00b950_aoproject_value
on project.ID=ao_00b950_aoproject_value.PROJECT_ID
and ao_00b950_aoproject_value.FIELD_ID =1) as T1
left join ao_00b950_aoproject_value
on T1.ID = ao_00b950_aoproject_value.project_ID
and ao_00b950_aoproject_value.field_ID=26) as T2
left join ao_00b950_aoproject_value
on T2.ID = ao_00b950_aoproject_value.project_ID
and ao_00b950_aoproject_value.field_ID=28) as T3
left join ao_00b950_aoproject_value
on T3.ID = ao_00b950_aoproject_value.project_ID
and ao_00b950_aoproject_value.field_ID=27) as ww
set project.LEAD = 'kami'
where project.ID ='10000';
But unfortunately, it's not working and I'm not surprised because I'm not an expert in MySQL.
Does anybody have any suggestions?
Or I'm writing wrong the code like always.
With the first query, I get my result, and run perfectly.
With the second one, I get an error code 1288 "The target table ww of the UPDATE is not updatable".

Combining multiple queries into a single one

I have a simple query:
SELECT t1.tbl,
t1.slug
FROM t1
WHERE tags = '%".$tag."%'
However, I need to augment my results with the data from other tables (t2, t3, t4 and t5).
For example, if t1.tbl = 't2' I need to add from:
SELECT t2.title
FROM t2
WHERE t2.county = '".$county."'
which I could join like this:
LEFT JOIN ON (t1.rid = t2.id)
In each of there tables I'll filter by $county even though the column is named differently.
I've tried something like this:
SELECT t1.tbl,
t1.slug
FROM t1 A
LEFT JOIN (
SELECT title
FROM t2 B
WHERE A.tbl = 't2'
) ON (A.rid = B.id)
WHERE A.tags = '%".$tag."%'
Is there a way to combine all there into a single query?
SELECT A.tbl,
A.slug,
COALESCE(B.title, C.title) AS title
FROM t1 A
LEFT JOIN t2 B
ON A.tbl = 't2' AND A.rid = B.id AND B.county = ?
LEFT JOIN t3 C
ON A.tbl = 't3' AND A.rid = C.id AND C.region = ?
WHERE A.tags LIKE ?
AND COALESCE(B.id, C.id) IS NOT NULL;
The last condition is to return only rows from A that have a match among one of the joined tables.
I think that's enough to see the pattern, so you can add more tables.
I urge you to learn to use query parameters instead of concatenating variables directly into your SQL string. It's easier to write the code and more secure from SQL injection vulnerabilities if you use query parameters.

MySQL - Joining table on itself based on criteria from other table

Here’s the problem I am trying to solve:
Table1 has Product ID’s, dates, and prices for those dates, Table2 has Product attributes.
I want to be able to compare prices for a client for different products on the same date based on a set of attributes. I’m easily able to get a list of products/dates/prices for a ‘simple’ product, as well as an ‘advanced’ product (see below).
I want to be able to join these two tables such that the output looks like:
[CLIENT] [PRODUCT] [DATE] [SIM_PROD] [SIM_PRICE] [ADV_PROD] [ADV_PRICE]
Here is as far as I've made it
SELECT b.NAME AS ‘CLIENT’, a.NAME AS ‘SIMPLE_PRODUCT’, t1.DATE AS ‘DATE’, t1.PIVOT_PRICE AS ‘SIMPLE_PRICE’
FROM TABLE1 t1
LEFT JOIN PRODUCT a
ON t1.PRODUCT_ID = a_PRODUCT_ID
LEFT JOIN CLIENTS b
ON a.PARTNER_ID = b.PARTNER_ID
WHERE a.CRITERIA = TRUE;
SELECT b.NAME AS ‘CLIENT’, a.NAME AS ‘ADV_PRODUCT’, t2.DATE AS ‘DATE’, t2.PIVOT_PRICE AS ‘ADV_PRICE’
FROM TABLE1 t2
LEFT JOIN PRODUCT a
ON t2.PRODUCT_ID = a_PRODUCT_ID
LEFT JOIN CLIENTS b
ON a.PARTNER_ID = b.PARTNER_ID
WHERE a.CRITERIA = FALSE;
I've been able to build similar tables where I pull in price from TABLE1 labeling it as t1 then pull in price again from TABLE1 and labeling it as t2, but only when using criteria in TABLE1, not criteria in a table that needs to be joined.
Is it possible to 'set' a table (EG simple) then 'set' a second one (EG advanced) and then join them on PARTNER_ID and DATE?
You can join the two subqueries:
SELECT t1.client, t1.date, t1.simple_product, t1.simple_price, t2.adv_product, t2.adv_price
FROM (
SELECT b.NAME AS CLIENT, a.NAME AS SIMPLE_PRODUCT, t1.DATE, t1.PIVOT_PRICE AS SIMPLE_PRICE
FROM TABLE1 t1
LEFT JOIN PRODUCT a
ON t1.PRODUCT_ID = a_PRODUCT_ID
LEFT JOIN CLIENTS b
ON a.PARTNER_ID = b.PARTNER_ID
WHERE a.CRITERIA = TRUE
) AS t1
JOIN (
SELECT b.NAME AS CLIENT, a.NAME AS SIMPLE_PRODUCT, t1.DATE, t1.PIVOT_PRICE AS SIMPLE_PRICE
FROM TABLE1 t1
LEFT JOIN PRODUCT a
ON t1.PRODUCT_ID = a_PRODUCT_ID
LEFT JOIN CLIENTS b
ON a.PARTNER_ID = b.PARTNER_ID
WHERE a.CRITERIA = FALSE
) AS t2
ON t1.client = t2.client AND t1.date = t2.date
You'll probably need to select additional criteria and add them to the ON condition. Otherwise this will produce a full cross product between all the products that have the same client and date.
Your desired output has an additional PRODUCT column, but I couldn't see where that comes from.

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.

MySql: merge three tables together

I want to merge three tables together as shown here:
Basically I want to include the items from all three tables T1, T2 and T3 and have them merged as shown in the result table. I tried something like this:
SELECT T1.user, T2.tid, T2.name, T3.type, T1.mid
FROM T1
LEFT JOIN T2 ON T1.mid = T2.mid
LEFT JOIN T3 ON T2.tid = T3.tid
GROUP BY T1.user;
But it does not seem to have worked. It does show the results but only unique values. In the result if user is johny, it will only show the first value and ignore the second, though it should be in the result table.
Is there something I am missing?
The Group is not necessary if you want to see all results for each of the users. Otherwise it will hide some of the rows and show just one per user.
First join T1 Right to T2 than Left Join to T3. This is good practice if there is element from T1 that has no connection with element from T3 to prevent showing NULL result for T£ fields.
SELECT T1.user, T2.tid, T2.name, T3.type, T1.mid
FROM T1
RIGHT JOIN T2 ON T1.mid = T2.mid
LEFT JOIN T3 ON T2.tid = T3.tid;
Get rid of the "Group By" part. This should fix your problem.
Eliminate the GROUP BY. There's no need for it in this query.
SELECT T1.user, T2.tid, T2.name, T3.type, T1.mid
FROM T1
LEFT JOIN T2 ON T1.mid = T2.mid
LEFT JOIN T3 ON T2.tid = T3.tid;