Разработка базы данных с передовой практикой для отслеживания прогресса через связанные таблицы (несколько левых объединений) - PullRequest
0 голосов
/ 17 февраля 2012

У меня есть приложение базы данных 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 голосов
/ 07 марта 2012

Мне не совсем понятно, для чего вы это используете, но похоже, что ваш сценарий использования может выиграть от использования сводных таблиц. Microsoft Excel и Microsoft Access имеют их, вероятно, также проще в настройке.

По сути, вы настраиваете запрос, который объединяет все связанные с вами данные, возможно, с некоторыми параметрами, которые пользователь будет заполнять (ускоряет работу, если у вас большие объемы данных), а затем передает результат в сводную таблицу и тогда вы можете группировать вещи так, как вы хотите. Вы можете на лету просматривать подпроекты по библиотекам, образцы по машинам, библиотеки по образцам, а также фильтровать любые из этих полей. Таким образом, вы можете быстро составить отчет «Образцы по машине» и отфильтровать его, чтобы отображались только образцы для машины 1.

Преимущество состоит в том, что вы делаете один запрос, который включает в себя все данные, которые вам могут понадобиться, а затем вы можете сосредоточиться на простой организации групп и фильтрации. Для такого рода вещей существуют более мощные системы (OLAP-серверы), но вам это может не понадобиться, если у вас нет огромных объемов данных.

0 голосов
/ 18 февраля 2012

А как насчет создания отдельных представлений для каждого Project_Id?

Если вы оставите структуру базы данных как есть и добавите ее в процессе работы приложения.Вы можете создать отдельное представление для каждого этапа или Project_Id.Если имеется 30 этапов (Project_Id 1..30), создайте 30 отдельных видов.

При добавлении нового этапа ... создайте новый вид.

...