Sql server 使用SQL Server,如何在三个单独的表之间进行查询,并在三个表之间的公共列上进行外部连接?

Sql server 使用SQL Server,如何在三个单独的表之间进行查询,并在三个表之间的公共列上进行外部连接?,sql-server,tsql,Sql Server,Tsql,我希望从给定的结构中获得以下输出。我已经包括了我在这个查询中的尝试,但它有一个基本问题。在数百万条记录中,使用公共日期会失去效率,因为它将在breakfasts表(例如)中查询breakfasts表中不存在的日期 期望输出: /* DESIRED OUTPUT Date BreakfastAttendees LunchAttendees DinnerAttendees 2016-01-01 10

我希望从给定的结构中获得以下输出。我已经包括了我在这个查询中的尝试,但它有一个基本问题。在数百万条记录中,使用公共日期会失去效率,因为它将在breakfasts表(例如)中查询breakfasts表中不存在的日期

期望输出:

/*
DESIRED OUTPUT
Date            BreakfastAttendees      LunchAttendees              DinnerAttendees
2016-01-01  10                      10                          10
2016-02-01  NULL                    10                          10
2016-03-01  NULL                    NULL                        10
*/
结构

declare @breakfasts table(Date datetime, Attendees int);
declare @lunches table(Date datetime, Attendees int);
declare @dinners table(Date datetime, Attendees int);

insert into @breakfasts values('01/01/2016',10);

insert into @lunches values('01/01/2016',10);
insert into @lunches values('02/01/2016',10);

insert into @dinners values('01/01/2016',10);
insert into @dinners values('02/01/2016',10);
insert into @dinners values('03/01/2016',10);
尝试

;With CommonDates_cte as 
(
    select distinct Date
    from @breakfasts

    union

    select distinct Date
    from @lunches

    union

    select distinct Date
    from @dinners
)
select 
    cte.Date, BreakfastAttendees, LunchAttendees, DinnerAttendees
from 
    CommonDates_cte cte
cross apply 
    (select 
         SUM(Attendees) AS BreakfastAttendees
     from @breakfasts b
     where b.Date = cte.Date) b
cross apply 
    (select 
         SUM(Attendees) AS LunchAttendees
     from @lunches l
     where l.Date = cte.Date) l
cross apply 
    (select 
         SUM(Attendees) AS DinnerAttendees
     from @dinners d
     where d.Date = cte.Date) d

您可以尝试此查询:

SELECT COALESCE(b.[Date], l.[Date], d.[Date]),
       SUM(b.Attendees) AS BreakfastAttendees,
       SUM(l.Attendees) AS LunchAttendees,
       SUM(d.Attendees) AS DinnerfastAttendees
FROM @breakfasts AS b
FULL JOIN @lunches AS l ON b.[Date] = l.[Date]
FULL JOIN @dinners AS d ON d.[Date] = l.[Date]
GROUP BY COALESCE(b.[Date], l.[Date], d.[Date])

该查询假设所有三个表的任何给定日期只有一条记录。

您可以尝试此查询:

SELECT COALESCE(b.[Date], l.[Date], d.[Date]),
       SUM(b.Attendees) AS BreakfastAttendees,
       SUM(l.Attendees) AS LunchAttendees,
       SUM(d.Attendees) AS DinnerfastAttendees
FROM @breakfasts AS b
FULL JOIN @lunches AS l ON b.[Date] = l.[Date]
FULL JOIN @dinners AS d ON d.[Date] = l.[Date]
GROUP BY COALESCE(b.[Date], l.[Date], d.[Date])

查询假设所有三个表的任何给定日期只有一条记录。

此假设日期可以重复
如果没有,还有更好的答案

;With CommonDates_cte as (
    select Date
         , Attendees as BreakfastAttendees 
         , 0         as LunchAttendees 
         , 0         as DinnerAttendees
    from @breakfasts   
    union all 
    select Date
         , 0         as BreakfastAttendees 
         , Attendees as LunchAttendees 
         , 0         as DinnerAttendees
    from @lunches
    union all 
    select Date
         , 0         as BreakfastAttendees 
         , 0         as LunchAttendees 
         , Attendees as DinnerAttendees 
    from @dinners
)
select date, sum(BreakfastAttendees), sum(LunchAttendees), sum(DinnerAttendees)
from CommonDates_cte 
group by date

若日期不重复,则

SELECT COALESCE(b.[Date], l.[Date], d.[Date]),
       b.Attendees AS BreakfastAttendees,
       l.Attendees AS LunchAttendees,
       d.Attendees AS DinnerfastAttendees
FROM      @breakfasts AS b
FULL JOIN @lunches    AS l ON l.[Date] = b.[Date]
FULL JOIN @dinners    AS d ON d.[Date] = b.[Date]

这假设日期可以重复
如果没有,还有更好的答案

;With CommonDates_cte as (
    select Date
         , Attendees as BreakfastAttendees 
         , 0         as LunchAttendees 
         , 0         as DinnerAttendees
    from @breakfasts   
    union all 
    select Date
         , 0         as BreakfastAttendees 
         , Attendees as LunchAttendees 
         , 0         as DinnerAttendees
    from @lunches
    union all 
    select Date
         , 0         as BreakfastAttendees 
         , 0         as LunchAttendees 
         , Attendees as DinnerAttendees 
    from @dinners
)
select date, sum(BreakfastAttendees), sum(LunchAttendees), sum(DinnerAttendees)
from CommonDates_cte 
group by date

若日期不重复,则

SELECT COALESCE(b.[Date], l.[Date], d.[Date]),
       b.Attendees AS BreakfastAttendees,
       l.Attendees AS LunchAttendees,
       d.Attendees AS DinnerfastAttendees
FROM      @breakfasts AS b
FULL JOIN @lunches    AS l ON l.[Date] = b.[Date]
FULL JOIN @dinners    AS d ON d.[Date] = b.[Date]

你真的需要求和吗?日期是否可以在表中重复?您的
联合体上不需要
独立的
根据定义,联合体将从结果中删除重复的值。您真的需要求和吗?表中的日期是否可以重复?您不需要
联合体上的
独立的
联合体
根据定义将从结果中删除重复的值。这里的问题是,一个重复的日期将导致其他重复的日期,并导致不正确的总和。@PhilipKelley是的,您是对的,
COALESCE
接受数量可变的参数。谢谢。如果你想假设所有三个表的任何给定日期都只有一条记录,那么你不需要group by或sum。这是一种有趣的方法,我试过了。它的运行速度没有@Papazzi的方法快。这里的问题是一个重复的日期会导致另一个重复,并导致不正确的总和。@PhilipKelley是的,你是对的,
COALESCE
接受可变数量的参数。谢谢。如果你想假设所有三个表的任何给定日期都只有一条记录,那么你不需要group by或sum。这是一种有趣的方法,我试过了。它没有@Papazzi的方法运行得那么快。顶级版本对我来说运行得很好,并且为最终的输出选择留下了一个干净的查询。我认为在不改变结果的情况下,“联合所有人”会稍微快一点。我会再做一些实验,但这是解决方案。谢谢。最上面的版本对我来说运行得很好,为最终的输出选择留下了一个干净的查询。我认为在不改变结果的情况下,“联合所有人”会稍微快一点。我会再做一些实验,但这是解决方案。谢谢