【问题标题】:How to join a primary key to two foreign keys in MySQL when the foreign keys will be different?当外键不同时,如何将主键连接到 MySQL 中的两个外键?
【发布时间】:2017-12-12 16:32:17
【问题描述】:

所以,我的问题是:我在一家销售公司工作,正在开发一个应用程序,使用 MS Access 2007 作为前端,MySQL 5.6 Server 作为后端。我正在尝试生成一个计算每个代表的佣金数据的视图。

我的 DDL 如下:

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)
;

想要的结果:

+------------+-------------+------------+----------+----------+
| 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

编辑 (2017-12-13):请注意员工 2346“Shana”如何以 1.50 美元的价格进行一次验证 (recap_id=423670)。她还有一个自我验证销售 (recap_id=423674),另外还有 0.50 美元的验证佣金和 5.75 美元的销售。这些必须单独跟踪。

正如您从 Fiddle 中看到的那样,我可以使用 Union 查询让数据以我想要的方式显示。当我在“回顾”中加载 4100 条员工记录和 236K 销售条目时,问题就出现了。阅读后,我了解到我的查询现在需要很长时间(大约 30 秒),因为 MySQL 正在从联合创建一个临时表,然后从未索引的临时表执行外部查询。当我为每个联合添加 WHERE 子句时,时间会大大减少。

我觉得我必须缺少一些东西:一个特殊的内部连接,一些东西。尽管我每天都使用 MySQL,但我对 MySQL 还是很陌生(我的工作通常只需要一些 concat() 和偶尔的内部连接)。我对任何事情都持开放态度。 如果结果证明这是最好的选择,我不会部分重新设计我的表格(也许还有一点社区帮助)。

目标: 对于 emp_employees 表中的每个员工,我需要获取 tsr_cpo 字段的总和 (sum(RECAP.tsr_cpo) 其中 EMP.id = RECAP .tsr_id)。我还需要为验证销售的任何人获取 ver_cpo 的总和 (sum(RECAP.ver_cpo) where EMP.id = RECAP.ver_id)。

【问题讨论】:

  • @Strawberry 感谢您的编辑!现在看起来干净多了。我很啰嗦,并试图保持简短。

标签: mysql sql join ms-access-2007 mysql-5.6


【解决方案1】:

我查看了您的问题,我同意维护一堆 UNION 查询来创建上面提到的“所需结果”似乎非常昂贵且困难。

编辑 12-14-2017:根据您对我的回答的评论,我在下面做了一些更改。

我认为这可以通过两个相当简单的查询来完成。第一个查询名为qry_Comms,SQL 代码如下:

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;

然后,名为qry_TotalComms 的第二个查询具有以下 SQL 代码:

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;

qry_Comms 查询是获取所有所需数据的基本查询,第二个查询qry_TotalComms 应该将所有数据正确地组合在一起。因此,您所要做的就是将这两个查询都保存在您的 Access 数据库中,然后运行 ​​qry_TotalComms 查询。根据您上面的“期望结果”表(以及您对我的原始答案的评论),我认为这应该提供正确的结果。

另外,如果这些查询的执行速度仍然不够快,请尝试对 qry_Comms 查询使用 MS Access“传递”查询,这是可以在“查询”中选择的 MS Access 查询类型之一设计”功能区菜单。 Access“传递”查询将 SQL 代码直接发送到数据库服务器,让服务器进行处理并返回结果记录集。所有其他类型的 Access 查询实际上会将表数据全部复制到本地,然后在本地创建结果数据集,如果您正在处理大表,这可能会很慢而且成本很高。因此,在将 MySQL 或 SQL Server 与 Access 结合使用时,“Pass-Through”查询可以大大提高您的 Access 应用程序性能。

最后,您还可以在您的 MySQL 数据库上创建上述查询作为视图,然后直接从 Access 调用 qry_TotalComms 视图。这将是可能提高我上面给出的查询性能的第二种选择。

无论如何,我希望这些信息对您有所帮助,但是如果您对此有任何疑问,请告诉我,我会尽力帮助解决问题!

【讨论】:

  • 我以前试过你的查询。问题是这仅在 emp_employee.ID 和 x_recap.tsr_id 上加入。我需要计算 tsr_comm,其中 emp_employee.id = x_recap.tsr_id,我需要计算 ver_comm,其中 emp_employee.id = x_recap.ver_id。我会尝试编辑我的问题以更好地反映这一点。
  • 我绝对计划在可能的情况下使用传递查询。有什么其他建议可以单独加入每一列?
  • 感谢您的后续消息,我明白您所说的 ver_id 和 tsr_id 需要用于相同的 emp_employee.id。我已经在这里更新了我的答案,如果这个解决方案更适合你,请告诉我!
  • 工会确实为我提供了我需要的东西,但正如我的问题中所述,我试图找到一种方法来做到这一点,而无需工会会做的全表扫描(两次!)。一旦我加载了当前可用的数据,4100 条员工记录和 236K 销售条目,使用传递查询完成执行大约需要 30 秒。
  • 嗯,UNION 不是昂贵的部分,真正的分组才是昂贵的部分。但是,除非您限制数据(使用 WHERE 子句),否则不幸的是,您总是必须对两个表进行全表扫描才能加入这些记录。您可以尝试的另一件事是在“tsr_id”和“ver_id”列上设置索引,看看是否有帮助,因为这是从“x_recap”表中选择记录的方式,看起来这些字段没有被索引现在。加入大型数据集时,索引也可以在性能上产生巨大差异。这有帮助吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-23
  • 1970-01-01
  • 2013-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多