完全外部联接不起作用 - 需要 return 所有日期,无论是否为空 activity
Full Outer Join Not Working - Need to return all dates regardless of null activity
无论是否有 activity (tTimesheets table),我都需要 return 每个月的每个日期 (DATES table)
在设计器中构建了这个查询,我不太精通,但我正在努力使它工作:)
根据我的谷歌搜索,我认为 WHERE 子句与我的 FULL OUTER JOIN 混淆了。看起来派生的 table 可能是解决方案?或者可能需要将某些条件带入联接而不是 WHERE 子句。
我在派生的 table 上读过这个 BLOG 但就是想不通
再次感谢您的帮助!
SELECT tProjects.ProjectName,
tProjects.ProjectID,
Dates.Date,
Dates.MonthNameYear,
tUsers.id,
tUsers.Name,
sum(tTimesheets.ActivityTime) as Time,
tExpenses.ExpenseID,
tClients.ClientName
FROM tClients
INNER JOIN tProjects
INNER JOIN tTimesheets
ON tProjects.ProjectID = tTimesheets.ProjectID
INNER JOIN tUsers
ON tTimesheets.CreatedBy = tUsers.id
ON tClients.ClientID = tProjects.ClientID
LEFT OUTER JOIN tExpenses
INNER JOIN tExpenseType
ON tExpenses.CategoryId = tExpenseType.Id
ON tTimesheets.CreatedBy = tExpenses.CreatedBy
AND CAST(tTimesheets.ActivityDate AS date) = CAST(tExpenses.ExpenseDate AS DateTime)
AND tTimesheets.ProjectID = tExpenses.ProjectID
FULL OUTER JOIN Dates
ON CAST(tTimesheets.ActivityDate AS date) = CAST(Dates.Date AS date)
WHERE
(tProjects.ProjectName in (@parmProjects) OR tProjects.ProjectName is null)
AND
(Dates.MonthNameYear in (@parmDate) OR Dates.MonthNameYear is null)
AND
(tUsers.Name in (@parmUser) OR tUsers.Name is null)
GROUP BY
tUsers.Name,
tUsers.id,
Dates.Date,
Dates.MonthNameYear,
tProjects.ProjectName,
tProjects.ProjectID,
tExpenses.ExpenseID,
tClients.ClientName
ORDER BY Dates.Date
这里不需要 FULL JOIN
。您只需要从 Dates
和 LEFT JOIN
其他一切开始。
所有与其他 table 相关的 WHERE
条件都需要放在 ON
子句中。
补充说明:
CAST(... AS date)
在用作连接或过滤条件时效率低下。最好使用日期间隔范围。如果你有一个 Date
table,无论如何它应该被声明为 date
数据类型。我没有更改它,因为我不知道你的数据。
d.MonthNameYear in (@parmDate) OR d.MonthNameYear is null
有点可疑:为什么 MonthNameYear
在日期 table 上为空。 in (@parmDate)
很奇怪:它应该匹配列表吗?如果是这样,那是行不通的。
- 此外,像这样使用
OR
可能会导致性能问题
- 使用简短而有意义的 table 别名,它使查询更具可读性
SELECT p.ProjectName,
p.ProjectID,
d.Date,
d.MonthNameYear,
u.id,
u.Name,
sum(ts.ActivityTime) as Time,
e.ExpenseID,
c.ClientName
FROM Dates d
LEFT JOIN
(tClients c
INNER JOIN tProjects p
ON c.ClientID = p.ClientID
AND (p.ProjectName in (@parmProjects) OR p.ProjectName is null)
INNER JOIN tTimesheets ts
ON p.ProjectID = ts.ProjectID
INNER JOIN tUsers u
ON ts.CreatedBy = u.id
AND
(u.Name in (@parmUser) OR u.Name is null)
LEFT OUTER JOIN
(tExpenses e
INNER JOIN tExpenseType
ON e.CategoryId = et.Id
) ON ts.CreatedBy = e.CreatedBy
AND CAST(ts.ActivityDate AS date) = CAST(e.ExpenseDate AS DateTime)
AND ts.ProjectID = e.ProjectID
)
ON CAST(ts.ActivityDate AS date) = CAST(d.Date AS date)
WHERE
(d.MonthNameYear in (@parmDate) OR d.MonthNameYear is null)
GROUP BY
u.Name,
u.id,
d.Date,
d.MonthNameYear,
p.ProjectName,
p.ProjectID,
e.ExpenseID,
c.ClientName
ORDER BY d.Date;
另一种方法是将所有其他联接放在派生的 table 或 CTE 中。这有时会更容易写。
无论是否有 activity (tTimesheets table),我都需要 return 每个月的每个日期 (DATES table)
在设计器中构建了这个查询,我不太精通,但我正在努力使它工作:)
根据我的谷歌搜索,我认为 WHERE 子句与我的 FULL OUTER JOIN 混淆了。看起来派生的 table 可能是解决方案?或者可能需要将某些条件带入联接而不是 WHERE 子句。
我在派生的 table 上读过这个 BLOG 但就是想不通
再次感谢您的帮助!
SELECT tProjects.ProjectName,
tProjects.ProjectID,
Dates.Date,
Dates.MonthNameYear,
tUsers.id,
tUsers.Name,
sum(tTimesheets.ActivityTime) as Time,
tExpenses.ExpenseID,
tClients.ClientName
FROM tClients
INNER JOIN tProjects
INNER JOIN tTimesheets
ON tProjects.ProjectID = tTimesheets.ProjectID
INNER JOIN tUsers
ON tTimesheets.CreatedBy = tUsers.id
ON tClients.ClientID = tProjects.ClientID
LEFT OUTER JOIN tExpenses
INNER JOIN tExpenseType
ON tExpenses.CategoryId = tExpenseType.Id
ON tTimesheets.CreatedBy = tExpenses.CreatedBy
AND CAST(tTimesheets.ActivityDate AS date) = CAST(tExpenses.ExpenseDate AS DateTime)
AND tTimesheets.ProjectID = tExpenses.ProjectID
FULL OUTER JOIN Dates
ON CAST(tTimesheets.ActivityDate AS date) = CAST(Dates.Date AS date)
WHERE
(tProjects.ProjectName in (@parmProjects) OR tProjects.ProjectName is null)
AND
(Dates.MonthNameYear in (@parmDate) OR Dates.MonthNameYear is null)
AND
(tUsers.Name in (@parmUser) OR tUsers.Name is null)
GROUP BY
tUsers.Name,
tUsers.id,
Dates.Date,
Dates.MonthNameYear,
tProjects.ProjectName,
tProjects.ProjectID,
tExpenses.ExpenseID,
tClients.ClientName
ORDER BY Dates.Date
这里不需要 FULL JOIN
。您只需要从 Dates
和 LEFT JOIN
其他一切开始。
所有与其他 table 相关的 WHERE
条件都需要放在 ON
子句中。
补充说明:
CAST(... AS date)
在用作连接或过滤条件时效率低下。最好使用日期间隔范围。如果你有一个Date
table,无论如何它应该被声明为date
数据类型。我没有更改它,因为我不知道你的数据。d.MonthNameYear in (@parmDate) OR d.MonthNameYear is null
有点可疑:为什么MonthNameYear
在日期 table 上为空。in (@parmDate)
很奇怪:它应该匹配列表吗?如果是这样,那是行不通的。- 此外,像这样使用
OR
可能会导致性能问题 - 使用简短而有意义的 table 别名,它使查询更具可读性
SELECT p.ProjectName,
p.ProjectID,
d.Date,
d.MonthNameYear,
u.id,
u.Name,
sum(ts.ActivityTime) as Time,
e.ExpenseID,
c.ClientName
FROM Dates d
LEFT JOIN
(tClients c
INNER JOIN tProjects p
ON c.ClientID = p.ClientID
AND (p.ProjectName in (@parmProjects) OR p.ProjectName is null)
INNER JOIN tTimesheets ts
ON p.ProjectID = ts.ProjectID
INNER JOIN tUsers u
ON ts.CreatedBy = u.id
AND
(u.Name in (@parmUser) OR u.Name is null)
LEFT OUTER JOIN
(tExpenses e
INNER JOIN tExpenseType
ON e.CategoryId = et.Id
) ON ts.CreatedBy = e.CreatedBy
AND CAST(ts.ActivityDate AS date) = CAST(e.ExpenseDate AS DateTime)
AND ts.ProjectID = e.ProjectID
)
ON CAST(ts.ActivityDate AS date) = CAST(d.Date AS date)
WHERE
(d.MonthNameYear in (@parmDate) OR d.MonthNameYear is null)
GROUP BY
u.Name,
u.id,
d.Date,
d.MonthNameYear,
p.ProjectName,
p.ProjectID,
e.ExpenseID,
c.ClientName
ORDER BY d.Date;
另一种方法是将所有其他联接放在派生的 table 或 CTE 中。这有时会更容易写。