Reputation: 7093
I have found a few answers how to select a column from subquery, but it doesn't seem to be working if there is a subquery inside subquery.
My table relationships are as follow (simplified, with example):
Plans
| id | role_id
| --------------
| 4 | 2
Roles
| id | name
----------------
| 2 | Operator
Assignments
| role_name | user_id
| ---------------------
| Operator | 12
Table Plans
have foreign key role_id
to table Roles
column id
. And Table Roles
have foreign key id
to table Assignments
column role_name
.
I'm writing a query that would select Plans
but instead of role_id
I would show user_id
from table Assignments
.
I'm pretty close with my current work but I'm stuck at final step:
SELECT assigned_user, plan.id, plan.role_id
FROM `Plans` AS plan
LEFT JOIN (
SELECT roleTable.id, roleTable.name
FROM `Roles` AS roleTable
INNER JOIN (
SELECT base_assign.user_id AS assigned_user, base_assign.role_name
FROM `Assignments` AS base_assign) AS roleAssign
ON roleTable.name = roleAssign.role_name
) AS role
ON (plan.assignee_role = role.id)
Column assigned_user
on SELECT
part (line 1) is not found but I tried by adding alias inside of subquery SELECT
. How I can select base_assign.user_id
? Note that I (most likely) cannot modify database structure as it was given like this in the first place.
Upvotes: 0
Views: 1521
Reputation: 39477
You are creating subqueries too excessively and you don't even need subqueries for this. Subqueries can be materialized by optimzer in MySQL which can cause performance issues.
See https://dev.mysql.com/doc/refman/5.6/en/subquery-optimization.html
Try this using simple left join
s:
select a.user_id as assigned_user,
p.id,
p.role_id
from `Plans` p
left join `Roles` r on p.assignee_role = r.id
left join `Assignments` a on r.name = a.role_name;
You query wasn't working because you were not selecting the column while joining.
Your somewhat "fixed" code:
select assigned_user,
plan.id,
plan.role_id
from `Plans` as plan
left join (
select roleAssign.assigned_user roleTable.id,
roleTable.name
from `Roles` as roleTable
inner join (
select base_assign.user_id as assigned_user,
base_assign.role_name
from `Assignments` as base_assign
) as roleAssign on roleTable.name = roleAssign.role_name
) as role on (plan.assignee_role = role.id)
Upvotes: 1
Reputation: 1269873
You don't need subqueries for this. It is a little confusing what you are trying to do. The following will return all plans, even those with no roles
and no assignments
:
SELECT b.user_id as assigned_user, p.id, p.role_id
FROM Plans p LEFT JOIN
Roles r
ON p.role_id = r.id LEFT JOIN
Assignments a
ON a.name = r.name;
Subqueries are bad for two reasons. In MySQL, the are materialized. That means extra overhead for reading and writing the tables. Plus, you lose any indexes on them.
In your case, the subqueries just add layer upon layer of naming, and the names really do not help make your query more understandable.
Upvotes: 1