问题
I previously asked a question in regards to the same situation here but since I was so vague about my query, the provided solution didn't work for my specific case. Here's my second attempt at resolving this:
I have a series of tables that are connected in strange ways... Here's the end result I'm trying to achieve with my SELECT query:
|----|---------|----------|----------|---------------|---------------|------------|---------------|
| id | company | city | province | manager_name | manager_email | staff_name | staff_email |
|----|---------|----------|----------|---------------|---------------|------------|---------------|
| 1 | aaa | toronto | ON | John Smith | john@aaa.com | Steve Chan | steve@aaa.com |
| 2 | bbb | sudbury | ON | Tom Bell | tom@bbb.com | | |
| 3 | ccc | hamilton | ON | Bill Miller | bill@ccc.com | Jill Smith | jill@ccc.com |
|----|---------|----------|----------|---------------|---------------|------------|---------------|
It may be confusing without seeing the database structure, but here's my query:
SELECT
f.id,
f.firm_name company,
f.city,
f.province,
-- manager
CONCAT(b.first_name, ' ', b.last_name) manager_name,
b.primary_email manager_email
-- staff
-- CONCAT(c.first_name, ' ', s.last_name) staff_name,
-- c.primary_email staff_email
-- manager (alt attempt)
-- CASE
-- WHEN r.user_role_types_id = 7 THEN max(b.primary_email)
-- END AS manager_email,
-- staff (alt attempt)
-- CASE
-- WHEN r.user_role_types_id = 21 THEN max(b.primary_email)
-- END AS staff_email
FROM
projects p1
-- projects
JOIN
(
SELECT
id,
MAX(fiscal_year) max_year, -- latest of the fiscal years
firms_id
FROM
projects
GROUP BY
firms_id
) p2
ON p1.fiscal_year = p2.max_year
AND p1.firms_id = p2.firms_id
-- firms
JOIN (
SELECT
id,
firm_name,
is_cancelled,
deleted,
a.city,
a.province,
FROM
firms
-- address
JOIN (
SELECT
firms_id,
city,
province
FROM
addresses
) a
ON a.firms_id = id
) f
ON f.id = p1.firms_id
-- roles
JOIN (
SELECT
projects_id,
users_id,
user_role_types_id
FROM
project_user_roles
) r
ON r.projects_id = p1.id
-- managers
JOIN (
SELECT
id,
first_name,
last_name,
primary_email
FROM
users
) m
ON m.id = r.users_id
-- AND r.user_role_types_id = 7
-- staff
-- JOIN (
-- SELECT
-- id,
-- first_name,
-- last_name,
-- primary_email
-- FROM
-- users
-- ) s
-- ON s.id = r.users_id
-- AND r.user_role_types_id = 21
WHERE
p1.deleted = 0 -- project not deleted
AND f.is_cancelled = 0 -- firm not cancelled
AND f.deleted = 0 -- firm not deleted
AND
(
r.user_role_types_id = 7 -- managers only
OR r.user_role_types_id = 21 -- staff only
)
GROUP BY
f.id
ORDER BY
f.firm_name
Notes:
- I've left some of my previous / alternate attempts in there (commented out)
- Both managers and staff are stored in the same table with the same fields
first_name
,last_name
andprimary_email
... The only thing that separates a manager from a staff is theirr.user_role_types_id
, which is specified in the roles table- manager = 7, staff = 21
- I seem to be able to only grab the manager or the staff, not both... this is my main issue
Commenting out the manager
section at the top, the GROUP BY
section at the bottom, and un-commenting the CASE
statements was my latest attempt at getting both of these fields, but it produced results like the following:
|----|---------|----------|----------|---------------|---------------|
| id | company | city | province | manager_email | staff_email |
|----|---------|----------|----------|---------------|---------------|
| 1 | aaa | toronto | ON | john@aaa.com | |
| 1 | aaa | toronto | ON | | steve@aaa.com |
| 2 | bbb | sudbury | ON | tom@bbb.com | |
| 3 | ccc | hamilton | ON | bill@ccc.com | |
| 3 | ccc | hamilton | ON | | jill@ccc.com |
|----|---------|----------|----------|---------------|---------------|
While this brought me close to my goal, I still needed to do the following:
- group duplicate lines into 1, retaining both emails
- this specifically is what brought me to ask my previous question like I did
- grab the
manager_name
andstaff_name
fields
I'll be happy to clarify any of this further if needed, but basically, I just need to be able to grab both the manager
and staff
details... Any ideas?
Also let me know you have any suggestions on renaming / re-wording this question for better visibility... It was hard to find the words to use.
回答1:
I ended up figuring it out with help from both here and here! Here's my new query, just in case somebody else in this strange situation finds themselves here:
SELECT
f.id,
f.firm_name company,
f.city,
f.province,
f.region_type region,
f.industry_type industry,
-- manager
MAX(
CASE
WHEN r.user_role_types_id = 7
THEN CONCAT(u.first_name, ' ', u.last_name)
END
) AS manager_name,
MAX(
CASE
WHEN r.user_role_types_id = 7
THEN u.primary_email
END
) AS manager_email,
-- staff
MAX(
CASE
WHEN r.user_role_types_id = 21
THEN CONCAT(u.first_name, ' ', u.last_name)
END
) AS staff_name,
MAX(
CASE
WHEN r.user_role_types_id = 21
THEN u.primary_email
END
) AS staff_email
FROM
projects p1
-- projects
JOIN
(
SELECT
id,
MAX(fiscal_year) max_year, -- latest of the fiscal years
firms_id
FROM
projects
GROUP BY
firms_id
) p2
ON p1.fiscal_year = p2.max_year
AND p1.firms_id = p2.firms_id
-- firms
JOIN (
SELECT
id,
firm_name,
is_cancelled,
deleted,
a.city,
a.province
FROM
firms
-- address
JOIN (
SELECT
firms_id,
city,
province
FROM
addresses
) a
ON a.firms_id = id
) f
ON f.id = p1.firms_id
-- roles
JOIN (
SELECT
projects_id,
users_id,
user_role_types_id
FROM
project_user_roles
) r
ON r.projects_id = p1.id
-- users
JOIN (
SELECT
id,
first_name,
last_name,
primary_email
FROM
users
) u
ON u.id = r.users_id
WHERE
p1.deleted = 0 -- project not deleted
AND f.is_cancelled = 0 -- firm not cancelled
AND f.deleted = 0 -- firm not deleted
AND f.industry_type != ''
GROUP BY
f.id
ORDER BY
f.firm_name
来源:https://stackoverflow.com/questions/58959573/mysql-joining-the-same-table-twice-but-grabbing-different-results