简体   繁体   中英

Select Row for Max Sum Value In Multiple Tables MYSQL

I need to query for the users with highest amount of sales by all projects, where the users are in users table, sales in units table, projects in projects table.

Projects     Top Agent    Total Sales for Project
Project A    User A       100000
Project B    User B        20000
Project C    User A         1000
Project D    -                 0

The Projects column is list all the projects regardless it has sales or not.

The Top Agent column is list the user with the highest sales in the project.

The Total Sales for Project is the total sales for a projects.

The agent column i got is incorrect because there is someone else has the highest sales, the query seems to return the first row of the result

SELECT projects, pid, CASE WHEN agent is null THEN '-' ELSE agent END as agent, 
CASE WHEN FORMAT(topagent,0) > 0 THEN FORMAT(topagent,0) ELSE 0 END as salesvolume 
FROM ( 
SELECT projects.name as projects, projects.id as pid, 
concat(users.f_name, ' ', users.l_name) as agent, 
SUM(units.price) AS topagent 
FROM users inner join bookings on bookings.agent_id = users.id 
inner join units on bookings.unit = units.id 
inner join types on types.id = units.types_id 
inner join projects on projects.id = types.project_id 
WHERE units.status = 'Sold' 
GROUP BY pid 
union 
select projects.name as projects, projects.id as pid, 
concat(users.f_name, ' ', users.l_name) as agent, 
SUM(units.price) AS topagent 
from projects left outer join types on projects.id = types.project_id 
left outer join units on types.id = units.types_id and units.status = 'Sold' 
left outer join bookings on units.id = bookings.unit and units.status = 'Sold' 
left outer join users on bookings.agent_id = users.id and units.status = 'Sold' 
group by pid 
) a 
GROUP BY pid 
order by topagent desc

Your column aliases are confusing to read. In English, it seems what you mean by topagent is "sum of sales by a human". But in SQL, your GROUP BY pid means that the SUM(units.price) really means "sum of sales in a project".

Then the UNION adds a list of projects to a list of users . The agent names are basically random at this point.

If I decipher the requirements as "a list of projects ranked by the sales values of each project's top sales agent", then you'd have SQL as below:

SELECT
  pid,
  projects.name as project_name,
  IFNULL(a.top_agent_name,'-') as top_agent_name,
  CASE WHEN FORMAT(top_agent_sales,0) > 0 THEN FORMAT(top_agent_sales,0) ELSE 0 END as top_agent_salesvolume
FROM
  projects
JOIN
  SELECT
    a.pid,
    a.agent_name as top_agent_name,
    a.agent_sales as top_agent_sales
  FROM
    (SELECT
      projects.id as pid,
      concat(users.f_name, ' ', users.l_name) as agent_name,
      SUM(units.price) AS agent_sales
    FROM users
      inner join bookings on bookings.agent_id = users.id
      inner join units on bookings.unit = units.id
      inner join types on types.id = units.types_id
      inner join projects on projects.id = types.project_id
    WHERE units.status = 'Sold'
    GROUP BY pid, users.id
    ) a # get all agents for all projects
  JOIN
    (SELECT
      MAX(agent_sales) as max_project_agent_sales
    FROM
      (SELECT
        projects.id as pid,
        SUM(units.price) AS agent_sales
      FROM users
        inner join bookings on bookings.agent_id = users.id
        inner join units on bookings.unit = units.id
        inner join types on types.id = units.types_id
        inner join projects on projects.id = types.project_id
      WHERE units.status = 'Sold'
      GROUP BY pid, users.id
      )
    GROUP BY pid) b ON a.pid = b.pid
    WHERE
      a.agent_sales = b.max_project_agent_sales

ORDER BY a.agent_sales desc

Old answer below:

There are 2 topagent s for each pid in the inner query since it's a union of 2 group by s. There isn't a reducing function in the outer group by pid so the topagent returned in the select is the first one that came up in the inner query.

Try it if helps you-

SELECT a.prjname, IFNULL(usr.name,'-') AS Top_Agent, SUM(a.sale) AS Total_Sales_for_Project
FROM 
(
SELECT prj.id AS prjid,prj.name AS prjname,usr.id,usr.name AS usrname,IFNULL(SUM(unit.price),0) AS sale
FROM projects AS prj 
LEFT JOIN `types` AS typ ON typ.project_id=prj.id 
LEFT JOIN units AS unt ON unt.type_id=typ.id AND unt.status='sold'
LEFT JOIN bookings bkg ON bkg.unit=unt.id 
LEFT JOIN users usr ON usr.id=bkg.agent_it 
GROUP BY prj.id,usr.id 
ORDER BY prj.id,usr.id,sale DESC 
) a 
GROUP BY a.prjid

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM