用于跟踪相关表格进度的最佳实践数据库设计(多个左连接)

时间:2012-02-17 18:02:00

标签: mysql sql database-design left-join

我有一个django数据库应用程序,它正在不断发展。

我们希望跟踪样本进展情况

sample ->  library -> machine -> statistics, etc. 

一般来说,每个阶段从左到右是一对多的关系。

这是我的数据库架构的简化版本

table sample
id    
name  

table library 
id     
name 
sample_id  (foreign key to sample table) 

table machine 
id
name
status
library_id  (foreign key to library table)

table sample_to_projects 
sample_id
project_id

table library_to_subprojects
library_id 
subproject_id

到目前为止它一直没问题,除了现在,一切都需要由项目查看。每个阶段可以属于一个或多个项目。我在项目和现有表之间添加了many_to_many关系。

我正在尝试创建一些执行多个左连接的视图,并显示项目的示例进度。

sample A
sample B   library_1    machine_1   
sample B   library_2    machine_2
sample C   library_3

首先尝试查询是这样的:

SELECT fields FROM
sample_to_projects , 
sample 
LEFT JOIN library ON sample.id = library.sample_id , 
library_to_project 
LEFT JOIN machine ON machine.library_id = library.id
WHERE 
    sample_to_project.project_id = 30 
    AND sample_to_project.sample_id = sample.id
    AND library_to_project.project_id = 30
    AND library_to_project.library_id = library_id

这里的问题是LEFT JOIN在WHERE子句之前完成。

因此,如果我们有一个属于project_A和project_B的样本。 如果示例具有project_B的库,但我们想要对project_A进行过滤,则LEFT JOIN不会为库列添加具有NULL的行(因为存在库)。但是,这些行会被WHERE子句过滤掉,并且样本不会显示出来。

reults filtering on project_A

sample_1(project_A, project_B)   library_A (project_A)
sample_1(project_A, project_B)   library_B (project_A, project_B)
sample_2(project_A, project_B)   library_C (project_B)  *this row gets filtered out, it should show only the sample details*

所以我的解决方案是在LEFT JOIN完成之前创建一个子查询来连接其他(右侧)表。

SELECT fields FROM
     sample_to_projects , 
     sample 
     LEFT JOIN (
          SELECT library.id as lib_id , library.sample_id as smaple_id ,  library.name as lib_name , machine_name 
          FROM library , 
          lib_to_projects ,  
          machine         
     ) 
     AS join_table ON sample.id = join_table.sample_id 
     WHERE 
         sample_to_project.project_id = 30 
         AND sample_to_project.sample_id = sample.id

问题是我的数据库的真实版本还有一些阶段,所以我需要为每个LEFT JOIN做一个嵌套的子查询。 SQL将变得非常大,难以阅读,我想知道在设计层面是否有更好的解决方案?它也不会很好地与Django模型一起玩(虽然如果我能让SQL工作,我会很开心)。

或者,有人可以针对此类问题提出某种最佳做法吗?我确信以组或类似方式显示用户必须相对普遍。如果有人知道一种适合django模型的方式会更好。

2 个答案:

答案 0 :(得分:0)

如何为每个Project_Id创建sepatate视图?

如果按原样保留数据库结构,并在应用程序进行时添加到数据库结构中。您可以为每个阶段或Project_Id创建单独的视图。如果有30个阶段(Project_Id 1..30),则创建30个单独的视图。

添加新舞台时......创建新视图。

答案 1 :(得分:0)

我对你正在使用它的内容并不十分清楚,但看起来你的用例可以从数据透视表中受益。 Microsoft Excel和Microsoft Access具有这些,可能也是最容易设置的。

基本上,您设置了一个将所有相关数据连接在一起的查询,可能包含用户填写的一些参数(如果您有大量数据,会使事情更快),然后将结果提供给数据透视表,然后你可以按照你想要的方式分组。您可以在运行中按库查看子项目,按机器查看样本​​,按样本查看库,以及过滤任何这些字段。因此,您可以快速生成Sample by Machine的报告,并对其进行过滤,以便只显示机器1的样品。

好处是您可以创建一个包含您可能需要的所有数据的查询,然后您可以专注于只安排组和过滤。这种东西有更多的重型系统(OLAP服务器),但如果你没有大量的数据,你可能不需要它。