如何在外部不工作时加入附加表

时间:2014-07-14 03:56:01

标签: sql-server

我有一个现有的过程,为了简洁起见,我已经砍掉了

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

这可能吗?

3 个答案:

答案 0 :(得分:0)

有可能。但是如果calWeekNumber表上有多个SchoolWeekYear行,则聚合函数会返回错误的结果。

答案 1 :(得分:0)

如果您希望显示SchoolWeekYear中的所有行,无论是否匹配,您都应使用RIGHT OUTER JOIN代替LEFT。

答案 2 :(得分:0)

您需要将SchoolWeekYear集成到早期阶段的现有表集中。

为了向您展示原则,让我们进一步简化问题。让我们有一个名为WeeklyData的表格,列WeekNumberSomeData。有些星期可能有多个条目,有些则没有。所以这个查询

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表包含在数据表之前。与前一种情况的不同之处在于,我们不会将StudentsStudentWeekly之间的联接结果与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首先是内部联合,然后结果集将是外部的加入了先前指定的连接的结果。