2016-05-13 2 views
0

Нужна помощь по этому запросу. Я пытаюсь создать запрос, который выбирает все родительские детали, и у меня есть другая таблица для присоединения, которая называется Family. Проблема заключается в том, что таблица Family содержит поле FamilyListID, которое содержит первичные ключи для учеников и родителей, разделенных с помощью возврата каретки. Конечно, там может быть несколько идентификаторов, так как у Учеников могут быть братья и сестры, поэтому все это хранится в этом поле.Могу ли я сделать несколько ключевых соединений в sql?

Есть ли способ, что я могу присоединиться к мульти Pupil.pk_PupilID, Father.pk_PersonID, Mother.pk_PersonID относиться к Family.FamilyListID, имея в виду, что не может быть Father.pk_PersonID или Mother.pk_PersonID в зависимости от обстоятельств ученика. Надеюсь, что это имеет смысл. Я знаю, что между семьей и учеником должна быть таблица объединений, но это структура, с которой я в настоящее время должен работать.

SELECT 
    Pupil.pk_PupilID, Pupildata.Title, Pupildata.Forename, 
    Pupildata.Surname, Pupildata.PreferredForename, 
    father.pk_PersonID, father.Title, father.Forename, father.Surname, 
    mother.pk_PersonID, mother.Title, mother.Forename, mother.Surname, 
    Pupil.Form, 
    Address.Address1, Address.Address2, Address.TownCity, Address.Postcode, 
    Address.Country, Address.County 
FROM 
    Pupil 
LEFT JOIN 
    PERSON AS Pupildata ON Pupil.pk_PupilID = Pupildata.pk_PersonID 
LEFT JOIN 
    RELATION AS rfather ON Pupil.pk_PupilID = rfather.fk_PersonID 
LEFT JOIN 
    PERSON AS father ON rfather.fk_RelatedPersonID = father.pk_PersonID 
LEFT JOIN 
    RELATION AS rmother ON Pupil.pk_PupilID = rmother.fk_PersonID 
LEFT JOIN 
    PERSON AS mother ON rmother.fk_RelatedPersonID = mother.pk_PersonID 
LEFT JOIN 
    PERSONADDRESS AS pa ON Pupil.pk_PupilID = pa.fk_PersonID 
LEFT JOIN 
    ADDRESS ON pa.fk_AddressID = Address.pk_AddressID 
WHERE 
    Pupil.pk_PupilID IN ('" & pks & "') 
    AND rfather.Relationship IN ('Father', 'Stepfather') 
    OR rmother.Relationship IN ('Mother', 'Stepmother') 
    AND Address.PrimaryAddress = 1 
ORDER BY 
    Pupildata.Forename ASC 
+0

перекрестите их все и смените ограничение на предложение where - большинство баз данных будут делать правильные вещи и фактически не запускать перекрестное соединение. –

+0

Должен сказать, что это действительно звучит как проблема с дизайном базы данных. Наличие нескольких ключей в одном текстовом поле, разделенных возвратом каретки, полностью нарушает назначение базы данных. Кажется, лучше иметь таблицу отношений, которая будет относить человека ко всем членам семьи, или, возможно, просто иметь семейную таблицу, к которой каждая связана. Итак, я бы поставил идентификатор семьи на таблицу Person, а не несколько идентификаторов личности в столбце таблицы Family. –

+0

Хорошо, что эта структура является уверенным неудачником на все времена, поэтому я исправлю ее сейчас. Нет никакого оправдания для хранения данных в строках с возвратом каретки в поле, а затем для вытягивания деталей для сравнения с другими таблицами. – HLGEM

ответ

1

Ваша проблема заключается в вашей структуре данных. Вам нужно вытащить нужные данные в временную таблицу, которая правильно структурирована, а затем выполнить присоединение или исправить вашу модель данных. Так я сделал это, используя функцию split. Их можно найти, если вы ищете для функций split. Выберите тот, который лучше всего соответствует вашим потребностям. Мне пришлось заменить CRLF на |, потому что моя функция позволяет использовать только один разделитель символов.

Если вы ищете, вы можете найти тот, который позволит вам использовать более длинный разделитель. Во всяком случае, это дает вам представление о том, как получить данные в удобном для использования, к которым вы можете присоединиться. Этот код был написан на SQL-сервере. Я не предоставляю код функции, потому что, не зная, что у вас есть бэкэнда базы данных, сложно сказать, что будет работать точно, это больше указывает на то, что вам нужно делать.

Create table #test (Familyid int, Detail varchar(100)) 
insert into #test(Familyid, Detail) 
values (1, '1 '+char(13)+char(10)+ '2 ' +char(13)+char(10)+ '3') 
,(2, '4 '+char(13)+char(10)+ '5 ' +char(13)+char(10)+ '6') 
,(3, '7 '+char(13)+char(10)+ '8 ') 
select * from #test 

update #test 
set detail = replace (detail, char(13)+char(10), '|') 


select t.familyid, cast(splitdata as Int) as ID 
into #test2 
from #test t 
cross apply dbo.fn_Split_String (detail, '|') 

select * from #test2 

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

Если вы не можете заменить эту таблицу, посмотрите, можно ли создать другую таблицу, которая должным образом спроектирована, использовать функцию разделения, которую вы выберете, и заполнить ее, а затем сохранить ее с помощью триггеров на исходном планшете, который будет обновлять, удалять или вставить во вторую таблицу, поскольку записи изменяются в исходной таблице. Это компромиссное решение, но по крайней мере тогда вам нужно сделать только разделение на запись только тогда, когда данные меняются, а не каждый раз, когда вы запускаете запрос.

Смежные вопросы