我有一个现有的过程,为了简洁起见,我已经砍掉了
SELECT col1, col2
FROM (
col1, col2
SELECT col3--aggregate columns
FROM iep i
INNER JOIN student s ON s.studentID = i.studentID
INNER JOIN dbo.IDuration id ON i.IepID = id.iepID
INNER JOIN AppointmentStudent as ON s.studentID = as.studentID
INNER JOIN Appointment a ON as.appointmentID = a.appointmentID
INNER JOIN AppointmentTherapist at ON a.appointmentID = at.appointmentID
WHERE s.studentID = @studentID
GROUP BY col1, col2
) t
汇总列总结了一年中几周的约会,但只在学生预约的几周内完成。我有一个名为SchoolWeekYear的附加表,其中填充了我试图整合到此proc的一年中的所有星期,所以我得到52条记录,而不仅仅是我目前得到的少数记录。
SELECT col1, col2
FROM (
col1, col2
SELECT col3--aggregate columns
FROM iep i
INNER JOIN student s ON s.studentID = i.studentID
INNER JOIN dbo.IDuration id ON i.IepID = id.iepID
INNER JOIN AppointmentStudent as ON s.studentID = as.studentID
INNER JOIN Appointment a ON as.appointmentID = a.appointmentID
LEFT OUTER JOIN SchoolWeekYear swy on a.calWeekNumber = swy.calWeekNumber
INNER JOIN AppointmentTherapist at ON a.appointmentID = at.appointmentID
WHERE s.studentID = @studentID
GROUP BY col1, col2
) t
这可能吗?
答案 0 :(得分:0)
有可能。但是如果calWeekNumber
表上有多个SchoolWeekYear
行,则聚合函数会返回错误的结果。
答案 1 :(得分:0)
如果您希望显示SchoolWeekYear
中的所有行,无论是否匹配,您都应使用RIGHT OUTER JOIN
代替LEFT。
答案 2 :(得分:0)
您需要将SchoolWeekYear
集成到早期阶段的现有表集中。
为了向您展示原则,让我们进一步简化问题。让我们有一个名为WeeklyData
的表格,列WeekNumber
和SomeData
。有些星期可能有多个条目,有些则没有。所以这个查询
SELECT
WeekNumber,
AGG(SomeData)
FROM
WeeklyData
GROUP BY
WeekNumber
;
只返回WeeklyData
中存在的几周。如果要返回所有周的数据,请使用相应的参考表(将其称为AllWeeks
),如下所示:
SELECT
aw.WeekNumber,
AGG(wd.SomeData)
FROM
AllWeeks AS aw
LEFT JOIN
WeeklyData AS wd ON aw.WeekNumber = wd.WeekNumber
GROUP BY
aw.WeekNumber
;
所以,你拿参考表(AllWeeks
)并加入数据表(WeeklyData
)到它,而不是另一轮。
现在,如果原始查询稍微复杂一下怎么办?现在让我们假设数据表名为StudentWeeklyData
,并且有一个名为StudentID
的列,它是对Students
表的引用。我们还假设查询与您的查询类似,因为它在数据表加入之前逻辑上包含Students
表,并在Students
的主键上过滤结果:
SELECT
s.StudentID,
s.StudentName,
swd.WeekNumber,
AGG(swd.SomeData)
FROM
Students AS s
INNER JOIN
StudentWeeklyData AS swd ON s.StudentID = swd.StudentID
WHERE
s.StudentID = @StudentID
GROUP BY
s.StudentID,
s.StudentName,
swd.WeekNumber
;
(并非每个细节都很重要,我只是想为你使用一个更加类似的例子,这个例子仍然很容易理解。)同样,这将只返回指定学生在StudentWeeklyTable
中有数据的几周。如果你想为学生返回所有周(当然其中一些可能是空的),你可以这样做:
SELECT
s.StudentID,
s.StudentName,
aw.WeekNumber,
AGG(swd.SomeData)
FROM
Students AS s
CROSS JOIN
AllWeeks AS aw
LEFT JOIN
StudentWeeklyData AS swd ON s.StudentID = swd.StudentID
AND aw.WeekNumber = swd.WeekNumber
WHERE
s.StudentID = @StudentID
GROUP BY
s.StudentID,
s.StudentName,
aw.WeekNumber
;
在这里,您可以再次看到AllWeeks
表包含在数据表之前。与前一种情况的不同之处在于,我们不会将Students
和StudentWeekly
之间的联接结果与AllWeeks
联系起来,也不会将数据表本身专门用于{ {1}}。而是将数据表连接到交叉连接的结果AllWeeks
。
回到你的具体情况,我意识到在你的情况下甚至涉及更多的表。由于您没有指定所有这些表彼此之间的关系,我只能猜测Students × AllWeeks
应该在SchoolWeekYear
之后和此行之前交叉连接:
FROM
并且所述行应该像这样修改:
INNER JOIN Appointment a ON as.appointmentID = a.appointmentID
LEFT JOIN Appointment a ON as.appointmentID = a.appointmentID
AND swy.calWeekNumber = a.calWeekNumber
是分配给swy
的别名。
值得注意的是,后续的内联接SchoolWeekYear
。如果连接保持不变,那么该连接将消除上面左连接的影响,因为它的条件引用了AppointmentTherapist
表。也许,修复问题的语法最简单的方法是将内连接更改为左连接,尽管还有另一种方法:而不是
Appointment
您可以使用以下语法:
LEFT JOIN Appointment a ON as.appointmentID = a.appointmentID
AND swy.calWeekNumber = a.calWeekNumber
LEFT JOIN AppointmentTherapist at ON a.appointmentID = at.appointmentID
这样,加入的逻辑顺序就会改变:LEFT JOIN
Appointment a
INNER JOIN AppointmentTherapist at ON a.appointmentID = at.appointmentID
ON as.appointmentID = a.appointmentID
AND swy.calWeekNumber = a.calWeekNumber
和Appointment
首先是内部联合,然后结果集将是外部的加入了先前指定的连接的结果。