简体   繁体   中英

How to use a formula in a SQL query and sort on that result

In my company we use a leaderboard to show the performance of our sales agents. The leadersboard is shown in an HTML table. The leaderboard now only contains the amount of sales made of certain periods (today, this week and this month). Now I want to expand the leaderboard by adding the earned commissions by the agents of those periods. I use the following formula to calculate the commissions of a periode of sales agents in my company:

4*(x/y)*z

Where x is the total number of sales an agent made that month, y is the total hours an agent worked that month and z is the number of sales an agent made in a certain period (a day or a week). Thus in order to calculate the commission of an agent of a certain periode the performance of the rest of the month has to be taken in account.

I now have two MySQL data tables. One is called Sales and the other one is called Hours. Each entry in the Sales table represents one sale with the date (finalized_at) when the sale has been made and each entry in the Hours table represents a shift worked by the agent containing the hours worked and the date when the shift has taken place. The tables look like this:

Sales table

+-------+--------------+
| agent | finalized_at |
+-------+--------------+
| John  | 01-01-2020   |
+-------+--------------+
| John  | 02-01-2020   |
+-------+--------------+
| Mark  | 01-01-2020   |
+-------+--------------+
| Peter | 04-01-2020   |
+-------+--------------+
| John  | 04-01-2020   |
+-------+--------------+

Hours table

+-------+-------+------------+
| agent | hours | date       |
+-------+-------+------------+
| John  | 1     | 01-01-2020 |
+-------+-------+------------+
| John  | 5     | 02-01-2020 |
+-------+-------+------------+
| Mark  | 1     | 01-01-2020 |
+-------+-------+------------+
| Peter | 2     | 04-01-2020 |
+-------+-------+------------+
| John  | 4     | 04-01-2020 |
+-------+-------+------------+

I am now trying to run a query where I can calculate the earned commissions per agent sorted from high to low. Without creating a new data table to save the commissions. So if I would for example wanted to calculate the commissions earned on january 4th, I would have gotten the following result:

+-------+------------+
| agent | commission |
+-------+------------+
| Peter | 2          |
+-------+------------+
| John  | 1.2        |
+-------+------------+

So my question is: How can I structure one query where I use information from both data tables to calculate the commission per agent on a certain date.

For now I came up with this. But this doesn't seem to work. If gives me the following error message: Reference 'sales' not supported (reference to group function)

SELECT agent,
    COUNT(*) as sales,  
    (4*(SELECT COUNT(*) 
        FROM Sales Sales2 
        WHERE Sales2.agent=Sales.agent AND finalized_at BETWEEN '2020-01-01 00:00:00' AND '2020-01-31 23:59:59'))
        /           
        (SELECT SUM(hours) 
        FROM Hours 
        WHERE date BETWEEN '2020-01-01 00:00:00' AND '2020-01-31 23:59:59' AND agent=Sales.agent) as sph        
FROM Sales 
WHERE finalized_at BETWEEN '2020-01-04 00:00:00' AND '2020-01-04 23:59:59' 
GROUP BY agent 
ORDER by (sph*sales) DESC

You can put the query as sub query and sort the result, like this:

select * from (
  SELECT agent,
    COUNT(*) as sales,  
    (4*(SELECT COUNT(*) 
      FROM Sales Sales2 
      WHERE Sales2.agent=Sales.agent AND finalized_at BETWEEN '2020-01-01 00:00:00' AND '2020-01-31 23:59:59'))
      /           
      (SELECT SUM(hours) 
      FROM Hours 
      WHERE date BETWEEN '2020-01-01 00:00:00' AND '2020-01-31 23:59:59' AND agent=Sales.agent) as sph        
  FROM Sales 
  WHERE finalized_at BETWEEN '2020-01-04 00:00:00' AND '2020-01-04 23:59:59' 
  GROUP BY agent 
) r
order by sales * sph desc;

I do not know the nature of your data, but I would suggest you to use exclusive end instead of between, as follows:

select * from (
  SELECT agent,
    COUNT(*) as sales,  
    (4*(SELECT COUNT(*) 
      FROM Sales Sales2 
      WHERE Sales2.agent=Sales.agent AND finalized_at >= '2020-01-01' AND finalized_at < '2020-02-01'))
      /           
      (SELECT SUM(hours) 
      FROM Hours 
      WHERE date >= '2020-01-01' AND date < '2020-02-01' AND agent=Sales.agent) as sph        
  FROM Sales 
  WHERE finalized_at >= '2020-01-04' AND finalized_at < '2020-01-05'
  GROUP BY agent 
) r
order by sales * sph desc;

I once used between like the one you employed here BETWEEN '2020-01-04 00:00:00' AND '2020-01-04 23:59:59' and I missed records for 1 second interval 23:59:59 to 00:00:00

The complete working code at db-fiddle

You can order by the calculation, or by the alias you give to that calculation, a simple example of this is below, nb I have used descending order:

 CREATE TABLE hours( agent VARCHAR(7),hours INTEGER,date DATE ); INSERT INTO hours(agent,hours,date) VALUES ('John',1,'01-01-2020'); INSERT INTO hours(agent,hours,date) VALUES ('John',5,'02-01-2020'); INSERT INTO hours(agent,hours,date) VALUES ('Mark',1,'01-01-2020'); INSERT INTO hours(agent,hours,date) VALUES ('Peter',2,'04-01-2020'); INSERT INTO hours(agent,hours,date) VALUES ('John',4,'04-01-2020');
 select agent, sum(hours) as sum_hours from hours group by agent order by sum(hours) DESC /* repeat the calculation here */, agent
 agent | sum_hours:---- |  --------: John |  10 Peter |  2 Mark |  1 
 select agent, sum(hours) as sum_hours from hours group by agent order by sum_hours DESC /* or use the column alias here */, agent
 agent | sum_hours:---- |  --------: John |  10 Peter |  2 Mark |  1 

db<>fiddle Postgres here

db<>fiddle MySQL here

In order to count x you can use this query:

SELECT agent, COUNT(*) AS 'total number of sales in january' 
FROM  Sales
WHERE finilized_at BETWEEEN '01-01-2020' AND '31-01-2020'
GROUP BY 1;

In order to calculate y you can use this query:

SELECT agent, SUM(hours) 
FROM Hours
WHERE date BETWEEN '01-01-2020' AND '31-01-2020'
GROUP BY 1;

And to calculate z(a day) you can use this query:

SELECT agent, COUNT(*)
FROM Sales
WHERE finalized_at = '01-01-2020'
GROUP BY 1;

You can use ORDER BY statement to sort values. In the new table with results(let it be commissions) you would use it like this:

SELECT * FROM commisions
ORDER BY commission DESC;

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