Christopher Fernandes Ответов: 3

Sql join возвращает только одну строку из левой таблицы


У меня есть следующие таблицы Employee, EmployeeManager, EmployeeLeavesAssigned, EmployeeLeavesTaken, EmployeeLeaveCashed

Employee 1 to Many EmployeeManager (один сотрудник может иметь несколько менеджеров)
Employee 1 to Many EmployeeLeavesAssigned (одна запись для каждого сотрудника в календарном году)
Сотрудник 1 для многих EmployeeLeavesTaken (несколько записей для каждого сотрудника за один календарный год)
Сотрудник 1 для многих EmployeeLeaveCashed (несколько записей для каждого сотрудника за один календарный год)

Теперь, когда я пытаюсь создать SP, чтобы получить список всех листьев, обналиченных сотрудниками
это дает мне дублирующуюся строку для каждой записи в EmployeeLeaveCashed из-за таблицы EmployeeManager

Я использую left join, и левая таблица-EmployeeLeaveCashed, а правые таблицы-Employee & Employee Manager. Даже внятное не помогает.

Что я должен сделать, чтобы устранить эту дублирующуюся строку?

Вот этот запрос
ВЫБИРАТЬ
Эд.RefEmpID как [empid в]
,ED.EmpFirstName
,ED.EmpMiddleName
,ED.EmpLastName
,EMG.RefEMGID AS [ManagerID]
,ELC.RefELCID AS [ELCID]
,ELC.CashedDate
,ELC.CashedCount
,Елка.RefCalendarPeriodID как [платила]
,ELC.PeriodStartDate
,ELC.PeriodEndDate
,LTY.RefLeaveTypeID AS [LTYID]
,LTY.LeaveTypeName
От EmployeeLeaveCashed ELC
Левое соединение CalendarPeriod CP на ELC.RefCalendarPeriod = CP.RefCalendarPeriod
Левое соединение LeaveType LTY на ELC.RefLeaveTypeID = LTY.RefLeaveTypeID
Левое соединение работника на ЭЮК.RefEmpID = Эд.RefEmpID
Левое соединение EmployeeManager ГРП на ЭД.RefEmpID = ЭМГ.Рефемпид

Что я уже пробовал:

Я удалил таблицу EmployeeManager из соединения. Но мне нужно показать имя менеджера. Так что мне нужно иметь в СП.

Jörgen Andersson

Можете ли вы показать нам запрос?

Christopher Fernandes

ВЫБИРАТЬ
Эд.RefEmpID как [empid в]
,ED.EmpFirstName
,ED.EmpMiddleName
,ED.EmpLastName
,EMG.RefEMGID AS [ManagerID]
,ELC.RefELCID AS [ELCID]
,ELC.CashedDate
,ELC.CashedCount
,Елка.RefCalendarPeriodID как [платила]
,ELC.PeriodStartDate
,ELC.PeriodEndDate
,LTY.RefLeaveTypeID AS [LTYID]
,LTY.LeaveTypeName
От EmployeeLeaveCashed ELC
Левое соединение CalendarPeriod CP на ELC.RefCalendarPeriod = CP.RefCalendarPeriod
Левое соединение LeaveType LTY на ELC.RefLeaveTypeID = LTY.RefLeaveTypeID
Левое соединение работника на ЭЮК.RefEmpID = Эд.RefEmpID
Левое соединение EmployeeManager ГРП на ЭД.RefEmpID = ЭМГ.Рефемпид

Maciej Los

Пожалуйста, используйте Улучшить Вопрос[^] виджет и добавить выше содержание.

3 Ответов

Рейтинг:
2

Jörgen Andersson

Ну, проблема, очевидно, в том, что на одного сотрудника может приходиться более одного менеджера.

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

SELECT  ED.RefEmpID AS [EmpID]
       ,ED.EmpFirstName
       ,ED.EmpMiddleName
       ,ED.EmpLastName
       ,EMG.RefEMGID AS [ManagerID]
       ,COALESCE(
            STUFF
                (
                  (
                    SELECT  ', ' + EMG.RefEMGID
                      FROM  EmployeeManager EMG
                      WHERE ELC.RefEmpID = ED.RefEmpID
                      FOR XML PATH('')
                  ), 1, 2, N''
                )
            , N'') AS ManagerIDs
       ,ELC.RefELCID AS [ELCID]
       ,ELC.CashedDate
       ,ELC.CashedCount
       ,ELC.RefCalendarPeriodID AS [APID]
       ,ELC.PeriodStartDate
       ,ELC.PeriodEndDate
       ,LTY.RefLeaveTypeID AS [LTYID]
       ,LTY.LeaveTypeName
FROM    EmployeeLeaveCashed ELC
LEFT JOIN CalendarPeriod CP ON ELC.RefCalendarPeriod = CP.RefCalendarPeriod
LEFT JOIN LeaveType LTY ON ELC.RefLeaveTypeID = LTY.RefLeaveTypeID
LEFT JOIN Employee ED ON ELC.RefEmpID = ED.RefEmpID
Отрегулируйте по мере необходимости.


Stefan_Lang

Хорошая попытка, но я думаю, что Originalgriff (решение 2) прибил его: отношения неправильны.

Jörgen Andersson

Нет, вполне возможно иметь более одного менеджера. Например, один руководитель отдела одновременно с одним или несколькими руководителями проектов.
Однако, чтобы справиться с этим должным образом, Вам, очевидно, нужна другая структура БД.

Stefan_Lang

Я думал об этом, но все еще убежден, что нет смысла моделировать это таким образом. Административное отношение относится только к руководителю отдела, а не к руководителям проектов. Если вы хотите смоделировать отношения между проектами в своей БД, то вам необходимо создать таблицу проектов с отношением 1:1 для менеджера проекта и отношением 1:N для членов команды.

Рейтинг:
1

Stefan_Lang

Вы получили то, что просили: поля Select содержат поля из EmployeeManager и таблиц Employee. Конечно, у вас будет несколько записей на одного сотрудника!

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

П. С.: Как сказал Originalgriff в растворе 2, вы, вероятно, по образцу ваших отношениях диспетчере вверх ногами. Изменение этого должно решить проблему.


Рейтинг:
0

OriginalGriff

Я почти уверен, что это ваш дизайн БД, который сбивает вас с толку - он вообще не звучит правильно.
В частности:

Employee 1 to Many EmployeeManager (One employee can have multiple managers)
Кажется неправильным: у сотрудника обычно будет один менеджер, менеджер будет управлять несколькими сотрудниками.
Аналогично:
Employee 1 to Many EmployeeLeavesAssigned (one record for each employee per calendar year)
Employee 1 to Many EmployeeLeavesTaken (multiple records for each employee per calendar year)
Employee 1 to Many EmployeeLeaveCashed (multiple records for each employee per calendar year)
Это тоже звучит неправильно.
Я бы предположил, что у менеджеров есть сотрудники; у сотрудников есть YearlyLeaveRecords; у LeaveBooked есть YearlyLeaveRecords; у LeaveTaken есть YearlyLeaveRecords - это гораздо лучше отразит ситуацию "реального мира" и, вероятно, избавит от проблемы.

Таким образом, сотрудники имеют внешний ключ к менеджерам; YearlyLeaveRecords имеют внешний ключ к сотрудникам; LeaveBooked и LeaveTaken имеют внешние ключи к YearlyLeaveRecords.


Stefan_Lang

Помимо моих трудностей в понимании того, что должно означать присвоение/взятие/обналичивание*, я думаю, что ваше предложение имеет гораздо больше смысла.

*: когда я думаю об этом, соответствующие немецкие термины, используемые в нашей администрации, также не очень понятны ;-p

С. П.: Есть 5