【问题标题】:MySQL link table with extra fields creates cartesian product带有额外字段的 MySQL 链接表创建笛卡尔积
【发布时间】:2013-02-05 23:58:29
【问题描述】:

我正在尝试构建一个应用,该应用除了记录销售数量外,还保留主管与其团队之间的历史记录。

CREATE TABLE `emp` (
  `id` int(11) NOT NULL,
  `nombre` varchar(45) NOT NULL,
  `apellido` varchar(45) NOT NULL,
  `tl_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `tlFK_idx` (`tl_id`),
  CONSTRAINT `tlFK` FOREIGN KEY (`tl_id`) REFERENCES `emp` (`id`) 


CREATE TABLE `super` (
  `id` int(11) NOT NULL,
  `nombre` varchar(45) NOT NULL,
  `apellido` varchar(45) NOT NULL,
  PRIMARY KEY (`id`)
) 

CREATE TABLE `emp_super` (
  `emp_id` int(11) NOT NULL,
  `super_id` int(11) NOT NULL,
  `fecha` date NOT NULL,
  PRIMARY KEY (`emp_id`,`super_id`,`fecha`),
  KEY `empFK_idx` (`emp_id`),
  KEY `superFK_idx` (`super_id`),
  CONSTRAINT `empsuperFK` FOREIGN KEY (`emp_id`) REFERENCES `emp` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `super_empFK` FOREIGN KEY (`super_id`) REFERENCES `super` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
)

如您所见,表 emp_super 是链接表,但有一个日期字段。

emp_id super_id fecha
101863  101404  2012-10-15
101863  101503  2012-10-01
102403  101404  2012-10-15
102403  101503  2012-10-01
103052  101404  2012-10-15
103052  101503  2012-10-01
103718  101404  2012-10-15
103718  101503  2012-10-01

关键是要保留一个主管何时被分配到一个小组的记录,这样当有任何变化时,新的主管就不会继承他所在小组在前任领导下的表现。 我一直在进行查询以提取特定组的销售额,但我立即注意到,即使我认为我建立了所有正确的联系,我也会收到笛卡尔积。

这是销售表:

CREATE TABLE `sales` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `sale_date` date NOT NULL,
  `product_id` int(11) NOT NULL,
  `emp_id` int(11) NOT NULL,
  `qty` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `empFK_idx` (`emp_id`),
  KEY `campaignFK_idx` (`product_id`),
  CONSTRAINT `empFK` FOREIGN KEY (`emp_id`) REFERENCES `emp_super` (`emp_id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `productFK` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) 

通常,在处理日期时,我会尝试将日期限制在我的数据来自的主表中,但在这种情况下,我还需要考虑员工-主管关系的日期。

到目前为止我的查询是这样的:

SELECT s.sale_date,su.id,concat_ws(' ',su.nombre,su.apellido), p.name,e.id,concat_ws(' ',e.nombre,e.apellido), s.qty
from tracker.emp e, tracker.products p, tracker.sales s,tracker.super su, tracker.emp_super es
where e.id = es.emp_id
and su.id = es.super_id
and s.product_id = p.id
and e.id = s.emp_id
and s.sale_date between '2012-10-01' and '2012-10-15'
and es.fecha between '2012-10-01' and '2012-10-15'
order by su.id,p.name,e.id;

如果我将日期减少到 14 日,那么我会收到正确的结果,因为其他主管直到 15 日才加入。有没有人遇到过这样的业务要求:保持领导记录,以便新领导不加入继承前人的成就还是错误?

感谢您提出的任何建议。

【问题讨论】:

  • 我首先想到的是有一个字段来存储主管和工人之间关系结束的日期。
  • 我也很好奇emp.tl_id字段的作用。
  • tl_id 引用了员工与团队领导的关系。就问题而言,它不存在问题。

标签: mysql sql django-models


【解决方案1】:

您需要考虑监督角色何时结束。

这会给你,但我怀疑它不会很有效。

SELECT e1.emp_id 
      ,e1.super_id
      ,e1.fecha
      ,MIN(DATEADD(DAY, -1, e2.fecha)) AS end
FROM  emp_super e1
      INNER JOIN
      emp_super e2 ON e1.emp_id=e2.emp_id 
                      AND
                      e1.fecha<e2.fecha
GROUP BY e1.emp_id 
        ,e1.super_id
        ,e1.fecha

也许链接表上由TRIGGER 更新的结束列会更好?

【讨论】:

  • 我们想了很多,但最终一起选择了不同的设计。我现在不在工作,所以我没有代码,但一旦有,我会发布新设计并解释我们是如何计算出来的。我会说,就本项目的目的而言,维护历史数据并不仅仅通过员工-主管关系进行管理。当我有剩余的数据时,我会发布更多。
猜你喜欢
  • 2021-10-12
  • 2017-08-30
  • 2019-07-23
  • 2011-07-10
  • 2013-07-14
  • 1970-01-01
  • 2017-10-16
  • 2022-01-24
  • 2012-02-25
相关资源
最近更新 更多