MySQL - Joining the same table twice but grabbing different results

a 夏天 提交于 2019-12-14 03:06:25

问题


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 and primary_email... The only thing that separates a manager from a staff is their r.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 and staff_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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!