У меня есть три таблицы
Tasks
со столбцами Taskid, Taskname
TaskAllocations
со столбцами Taskid, EmpNum
TaskEntries
со столбцами TaskId, EmpNum, WorkedDate, Hoursspent
Теперь я хочу получить все записи задач в течение определенной недели. Здесь моя проблема даже в том случае, если для конкретной задачи нет Taskentry, я должен получить по крайней мере строку с этим TaskId, а Taskname с Hoursspent как Null в наборе результатов запроса. Я пытался получить это с помощью следующего запроса.
SELECT A.TaskId,
B.TaskName,
SUM( C.HoursSpent ) as TotalHours ,
C.WorkedDate, C.Comments
FROM TaskAllocations A
LEFT OUTER JOIN TaskEntries C
ON A.TaskId = C.TaskId
AND A.EmpNum = C.EmpNum
INNER JOIN Tasks B
ON A.TaskId = B.TaskId
WHERE A.EmpNum =123456
AND C.WorkedDate
IN ('2010-01-17','2010-01-18','2010-01-19',
'2010-01-20','2010-01-21','2010-01-22','2010-01-23' )
GROUP BY A.TaskId, C.WorkedDate
ORDER BY A.TaskId,C.WorkedDate ASC ';
То, что я получаю для этой части SQL, есть и только тогда, когда есть запись для определенного идентификатора задачи, тогда только я получаю строку для этого. но я хочу получить по крайней мере строку для каждой задачи, доступной для EmpNum. Даже если я получаю одну строку для каждой комбинации TaskId и WorkedDate, никаких проблем. Пожалуйста, помогите мне с этим. Фактическое намерение состоит в том, чтобы создать двумерную таблицу HTML с каждой записью задачи по дате и задаче, как показано ниже.
--------------------------------------------------------- TaskId TaskName Sun Mon Tue Wed Thu Fri Sat --------------------------------------------------------- 18 name1 2 3 4:30 3:30 19 name2 20 name3 4 2:30 22 name4 2:30 23 name5 24 name6 1:30 6 ---------------------------------------------------------
Таким образом, это может быть обновлено пользователем за каждую неделю. Сначала я подумал о group_concat, но из-за производительности я использую обычную группу по запросу.
Примечание: для конкретного taskid и workdate будет только одна запись hoursspent. Я почти построил интерфейс. Пожалуйста, помогите мне получить все идентификаторы задач, как указано выше, даже если нет записи. Нужно ли использовать подзапрос.
После тщательного тестирования различных вариантов я придумал решение ниже, которое даст мне необходимые результаты.
SELECT Final.TaskId,
Final.TaskName,
Tmp.HoursSpent AS TotalHours,
Tmp.WorkedDate
FROM (
SELECT A.TaskId, B.TaskName, A.EmpNum
FROM TaskAllocations A
INNER JOIN
Tasks B
ON ( A.TaskId = B.TaskId )
WHERE a.empnum = "333"
)Final
LEFT OUTER JOIN (
SELECT New.TaskId, New.EmpNum, New.WorkedDate, New.HoursSpent
FROM TaskEntries New
WHERE New.WorkedDate
IN
('2010-01-17','2010-01-18','2010-01-19',
'2010-01-20','2010-01-21','2010-01-22','2010-01-23' )
OR New.WorkedDate IS NULL
AND New.EmpNum = "333"
)Tmp
ON Tmp.TaskId = Final.TaskId
AND Tmp.EmpNum = Final.EmpNum
ORDER BY Final.TaskId, Tmp.WorkedDate ASC ;
Первый вопрос в моем вопросе не работал, так как я помещал условие в правый столбец таблицы при выполнении Left Outer Join. Спасибо всем за поддержку.
не использовать внутреннее соединение, использовать левое или правое соединение, в зависимости от значений, из которых вы хотите.
так:
SELECT *
FROM tasks t
LEFT JOIN taskentries te
ON t.id = te.id
который является тем же самым утверждением, что и:
SELECT *
FROM tasksentries te
RIGHT JOIN tasks t
ON te.id = t.id
предоставит вам все задачи, даже если нет задач
внутреннее соединение будет выбирать только строки, когда в обеих таблицах есть строки, левое соединение выбирает все строки из левой (первой) таблицы и сопоставляется с другой строкой (если такой строки нет, нуль будет значением все столбцы). правое соединение сделает oposite: выберите все строки из правой (второй) таблицы и сопоставьте их слева.
a LEFT JOIN b
совпадает с b RIGHT JOIN a