简体   繁体   中英

How to join a primary key to two foreign keys in MySQL when the foreign keys will be different?

So, my problem is this: I work with a sales company and am developing an app using MS Access 2007 as a front-end with MySQL 5.6 Server as the back-end. I'm trying to generate a view that calculates commission data for each rep.

My DDLs are as follows:

CREATE TABLE emp_employees
    (`id` int, `tsr_code` int, `first_name` varchar(9), `location_id` int)
;

INSERT INTO emp_employees
    (`id`, `tsr_code`, `first_name`, `location_id`)
VALUES
    (47, 829, 'ELIZABETH', 6),
    (199, 818, 'ERIC', 6),
    (1642, 301, 'JACK', 4),
    (2346, 619, 'SHANNA', 5),
    (2386, 899, 'MICHAEL', 3),
    (2490, 590, 'KARRIE', 4),
    (2642, 386, 'MINDI', 3),
    (2914, 615, 'REMELL', 3),
    (3150, 025, 'TEAL', 3),
    (3156, 609, 'JESSICA', 5)
;


CREATE TABLE x_recap
    (`recap_id` int, `sale_date` datetime, `location_id` int, `tsr_id` int, `ver_id` int, `tsr_cpo` decimal(10,4), `ver_cpo` decimal(10,4))
;

INSERT INTO x_recap
    (`recap_id`, `sale_date`, `location_id`, `tsr_id`, `ver_id`, `tsr_cpo`, `ver_cpo`)
VALUES
    (423670, '2017-01-23 08:15:44', 5, 3156, 2346, 9.0000, 1.5000),
    (423671, '2017-01-23 08:16:03', 6, 199, 47, 13.5000, 1.5000),
    (423672, '2017-01-23 08:16:41', 3, 3150, 2914, 4.7500, 0),
    (423673, '2017-01-23 08:17:08', 3, 2386, 2642, 8.7500, 1.50),
    (423674, '2017-01-23 08:17:28', 5, 2346, 2346, 5.7500, 0.50)
;

Desired result:

+------------+-------------+------------+----------+----------+
| sale_date  | location_id | first_name | tsr_comm | ver_comm |
+------------+-------------+------------+----------+----------+
| 2017-01-23 |           3 | MICHAEL    |   8.7500 |   0.0000 |
| 2017-01-23 |           3 | MINDI      |   0.0000 |   1.5000 |
| 2017-01-23 |           3 | REMELL     |   0.0000 |   0.0000 |
| 2017-01-23 |           3 | TEAL       |   4.7500 |   0.0000 |
| 2017-01-23 |           5 | JESSICA    |   9.0000 |   0.0000 |
| 2017-01-23 |           5 | SHANNA     |   5.7500 |   2.0000 |
| 2017-01-23 |           6 | ELIZABETH  |   0.0000 |   1.5000 |
| 2017-01-23 |           6 | ERIC       |  13.5000 |   0.0000 |
+------------+-------------+------------+----------+----------+

and SQL Fiddle of same .

EDIT (2017-12-13): Notice how employee 2346, "Shanna", has one verify (recap_id=423670) for $1.50. She also has a self-verified sale (recap_id=423674) for another $.50 in verify commission and $5.75 for the sale. These have to be kept track of separately.

As you can see from the Fiddle, I can get the data to appear the way I want it by using a Union query. The problem becomes when I load in 4100 employee records and 236K sale entries on the "recap". Having read up, I understand that my query now takes so long (about 30 seconds) because MySQL is creating a temporary table from the union and then preforming the outer query from the un-indexed temp table. The time drastically decreases when I add a WHERE clause to each of the Unions.

I feel there has to be something that I'm missing: a special inner join, something. I'm still fairly new to MySQL even though I use it everyday (my job usually only requires some concat() with an occasional inner join). I'm open to just about anything. I'm not beyond partially redesigning my tables if that turns out to be the best option (and maybe a little community help).

GOAL: For each employee in the emp_employees table, I need to get the sum of the tsr_cpo field (sum(RECAP.tsr_cpo) where EMP.id = RECAP.tsr_id). I also need to get the sum of ver_cpo for anyone who verified a sale (sum(RECAP.ver_cpo) where EMP.id = RECAP.ver_id).

I looked over your question and I agree that it would seem very expensive and difficult to maintain a bunch of UNION queries to create the "Desired Result" mentioned above.

EDIT 12-14-2017: Per your comment to my answer, I've made a few changes below.

I think this can be accomplished in two fairly simple queries. The first query, named qry_Comms , has the following SQL code:

SELECT x_recap.sale_date, emp_employees.location_id, emp_employees.id, emp_employees.first_name, Sum(x_recap.tsr_cpo) AS tsr_comm, 0 AS ver_comm
FROM x_recap INNER JOIN emp_employees ON x_recap.tsr_id = emp_employees.id
GROUP BY x_recap.sale_date, emp_employees.location_id, emp_employees.id, emp_employees.first_name, 0
UNION ALL 
SELECT x_recap.sale_date, emp_employees.location_id, emp_employees.id, emp_employees.first_name, 0 AS tsr_comm, Sum(x_recap.ver_cpo) AS ver_comm
FROM x_recap INNER JOIN emp_employees ON x_recap.ver_id = emp_employees.id
GROUP BY x_recap.sale_date, emp_employees.location_id, emp_employees.id, emp_employees.first_name, 0;

And then the second query, named qry_TotalComms , has the following SQL Code:

SELECT qry_Comms.sale_date, qry_Comms.location_id, qry_Comms.first_name, Sum(qry_Comms.tsr_comm) AS SumOftsr_comm, Sum(qry_Comms.ver_comm) AS SumOfver_comm
FROM qry_Comms
GROUP BY qry_Comms.sale_date, qry_Comms.location_id, qry_Comms.first_name, qry_Comms.id;

The qry_Comms query is the base query to get all the data needed, and the second query, qry_TotalComms , should group all the data together properly. So all you should have to do is save both of these queries in your Access database and then run the qry_TotalComms query. I think that should provide the correct results, per your "Desired Results" table above (and your comment to my original answer).

Also, if these queries still do not execute fast enough, try using an MS Access "Pass-Through" query for the qry_Comms query, which is one of the MS Access Query types that can be chosen on the "Query Design" Ribbon menu. An Access "Pass-Through" query sends the SQL code directly to the database server and lets the server do the processing and just returns the resulting recordset. All other types of Access queries will actually copy the table data all down locally and then create the resulting data set locally, which can be slow and expensive if you're dealing with big tables. So when using MySQL or SQL Server with Access, "Pass-Through" queries can greatly improve your Access application performance.

Lastly, you could also create the above queries I provided as views on your MySQL database, and then just call the qry_TotalComms view directly from Access. That would be a second alternative to possibly improving performance of the query I've given above.

Anyway, I hope this information helps, but please let me know if you have any questions about this and I will do my best to help solve the problem!

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