mysql - 检查多个表上的重复数据

标签 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

假设我有审批模板 与成员的“Manager Approver”:

Organization: BOD
JobLevel: Manager
JobTitle: General Manager 

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

另一种情况,我想再做一个有member的审批模板:

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

此模板无效,因为这将使员工 A 有 2 个符合条件的模板

为了检查这个组合是否重复,我创建了一个 View

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 Repository

@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 那么它是安全的/不与其他的重复。

我很清楚随着时间的推移会出现性能问题,有人可以推荐如何处理这个问题吗?每条建议都会很有帮助

最佳答案

我们无法在不知道要求的情况下验证您的数据库模型,因此我假设它是正确的。尽管您在 leveltitle 中有重叠,但看起来很可疑,例如seniorjunior developer 的组合似乎没有意义,但您可以将其插入到您的模板中(或者换句话说:使模板适用于所有 senior-jobs,无论如何你都需要在 titles 中列出它们,使 level 变得多余)。不过,这可能只是您的示例数据的产物,实际标题可能只是 Web Developer;但我会检查一下。

因为你没有在你的示例中提到它,我忽略了 steps-table(它似乎是一个版本控制系统),但你可以通过添加额外的 join 并且可能是一个group by step

您的验证确实需要一个join,但您应该让数据库对此进行评估,而不是使用 View 检索每个组合并自己对照所有组合进行检查。优化 join 并使用方法来限制中间结果集的大小(例如生成所有 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-table(和 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 或警告。

关于mysql - 检查多个表上的重复数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51996691/

相关文章:

mysql - 根据列值区分表,表中不能有任何其他条目

sql - 大型搜索中缺少 Cosmos DB 结果

c# - System.Data.dll 中发生类型为 'System.Data.SqlClient.SqlException' 的异常

python - 自定义 Django 数据库前端

php mysql fetch数组重复索引问题

mysql - 发票的历史价目表?

mysql - SQL查询根据表中的2条记录从1个表中获取记录

sql - 使用列与另一个列进行评估 oracle

php - PDO获取最后插入的ID

php - 多个用户访问同一个数据库表