检查多个表上的重复数据

时间:2018-08-24 02:32:17

标签: mysql sql database database-design

我们正在为公司分阶段实施审批系统。为此,要求说我们需要一个模板,用于根据组织,位置,职位级别,职务和工作类型对员工进行分组,因此具有相同模板的每个员工都具有相同的审批者步骤和层次。

这是高级ERD

这是我的问题。来自组织,位置等的数据只有几行。假设组织,位置和其他3个实体各有50行,那么我必须从50 ^ 5行中进行选择,以检查员工使用的是什么模板。

更不用说我需要检查组合是否与其他模板不相交,因此员工的模板不得超过1个

示例:

在此示例中,我仅使用组织,职位级别和职位

Employee A:
   Organization: BOD
   JobLevel: Manager
   JobTitle: General Manager

Employee B:
   Organization: ICT
   JobLevel: Senior
   JobTitle: Senior Web Developer

假设我有批准模板 拥有成员的“经理批准人”

Organization: BOD
JobLevel: Manager
JobTitle: General Manager 

此批准模板意味着...具有指定组织BOD,jobLevel Manager和jobTitle General Manager的所有员工都必须使用此模板。

另一种情况,我想与成员制作另一个批准模板:

Organization: BOD, ICT (note we can use combination here)
JobLevel: Manager, Senior
JobTITLE: General Manager, Senior Web Developer

此模板无效,因为这会使员工A有2个合格模板

为了检查此组合重复项,我创建了一个视图

CREATE OR REPLACE VIEW approval_template_members_view AS
    SELECT uuid() as id,
        at_organizations.organization_id AS organization_id,
        at_job_titles.job_title_id AS job_title_id,
        at_job_levels.job_level_id AS job_level_id,
        at.id AS approval_template_id
    FROM at
    INNER JOIN at_organizations ON at_organizations.approval_template_id = at.id
    INNER JOIN at_job_titles ON at_job_titles.approval_template_id = at.id
    INNER JOIN at_job_levels ON at_job_levels.approval_template_id = at.id;

要检查重复项,我只使用Jpa存储库

@Query("SELECT COUNT(m) From approval_template_members_view m where m.organization.id IN ?1 AND m.jobTitle.id IN ?2 AND m.jobLevel.id IN ?3")
Long countByMember(List<String> organizationIds, List<String> jobTitleIds, List<String> jobLevelIds);

然后检查此查询结果是否为0,那么它是安全的/不能与其他查询重复。

我非常了解随着时间的流逝会出现性能问题,有人可以建议如何处理吗?每个建议都会很有帮助

1 个答案:

答案 0 :(得分:0)

我们无法在不知道要求的情况下验证您的数据库模型,因此我认为它是正确的。尽管您在leveltitle中有重叠之处,例如,看起来有点可疑。 seniorjunior developer的组合似乎没有意义,但是您可以将其插入模板(或换句话说:使模板适用于所有senior-jobs,您仍然需要将它们全部列在titles中,从而使level变得多余)。不过,这可能只是示例数据的结果,实际标题可能只是Web Developer;但我会检查。

正如您在示例中未提到的那样,我忽略了steps表(它似乎是一个版本控制系统),但是您可以通过添加一个额外的join来包括它也许还有group by step

您的验证确实需要join,但是您应该让数据库对此进行评估,而不要使用视图检索每个组合并自己对照所有组合进行检查。优化join并具有限制中间结果集大小的方法(例如, not 不会生成所有50 ^ 5组合以检查其中是否存在特定组合)是一种面包关系数据库系统的黄油能力。

要验证您的任何模板中没有重复的条目,可以使用

select l.location_id, jt.job_title_id, jl.job_level_id, 
   count(*) as dupcount, group_concat(jt.id) as duplicates
from template_job_titles jt 
join template_locations l on jt.id = l.id
join template_job_levels jl on jt.id = jl.id
group by l.location_id, jt.job_title_id, jl.job_level_id
having count(*) > 1;

列出表的顺序无关紧要,因为实际的执行顺序是MySQL决定的事情之一。您想包含主approval_template表(和steps),为简单起见,我只是跳过了它。

要检查要添加的模板是否与任何现有模板相冲突(例如,如果要检查是否可以安全地从示例中添加组合模板(每个表有两个选项),请使用

select jt.id, l.location_id, jt.job_title_id, jl.job_level_id
from template_job_titles jt 
join template_locations l on jt.id = l.id
join template_job_levels jl on jt.id = jl.id
where (jt.job_title_id = 'General Manager' 
       or jt.job_title_id = 'Senior Web Developer')
  and (l.location_id = 'BOD' or l.location_id = 'ICT')
  and (jl.job_level_id = 'Senior' or jl.job_level_id = 'Manager');

这比第一个查询快得多。如果您从不添加有冲突的模板(例如,始终先检查并使用事务),则只需要第二个查询即可。

检查哪个用户具有哪个模板与询问基于用户信息的模板是否已在表中相同,因此它与第二个查询相同(当然不带组合);如果您怀疑只有一个模板,请添加group by或警告。