使用SQL Server如何在三个单独的表中查询外部连接在它们之间的公共列之间?

时间:2016-04-01 13:26:39

标签: sql-server tsql

我希望从给定的结构中获得以下输出。我已将此尝试包含在此查询中,但它存在根本问题。使用普通日期的数百万条记录会失去效率,因为它会查询早餐表(例如)早餐表中不存在的日期。

期望的输出:

/*
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

2 个答案:

答案 0 :(得分:3)

您可以尝试使用此查询:

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])

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

答案 1 :(得分:3)

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

;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

;With CommonDates_cteB as (
        select Date, sum(Attendees)  
        from @breakfasts 
        group by Date )
    , CommonDates_cteL as (
        select Date, sum(Attendees)  
        from @lunches
        group by Date ) 
    , CommonDates_cteD as (
        select Date, sum(Attendees)  
        from @dinners
        group by Date )
SELECT COALESCE(b.[Date], l.[Date], d.[Date]),
       b.Attendees AS BreakfastAttendees,
       l.Attendees AS LunchAttendees,
       d.Attendees AS DinnerfastAttendees
FROM      CommonDates_cteB AS b
FULL JOIN CommonDates_cteL AS l ON l.[Date] = b.[Date]
FULL JOIN CommonDates_cteD AS d ON d.[Date] = b.[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]