如何加入3个SQL查询

时间:2016-02-16 06:22:54

标签: sql-server join

这3个查询如何加入1。

我不是在寻找UNION ALL的结果。

每行我想要预测,预算,实际

SELECT 
    ps.PersonId, 
    SUM(TF.Hours * r.Amount) as Forecast
FROM ProjectStaffing ps
INNER JOIN Rate r on (r.ProviderId = ps.ProviderId AND r.OrganizationId = ps.OrganizationId AND r.RoleId = ps.RoleId)
INNER JOIN TimeForecast TF on (TF.ProjectStaffingId = ps.Id)
WHERE ps.ProjectId = @ProjectId
GROUP BY ps.PersonId

SELECT 
    ps.PersonId, 
    SUM(tb.Hours * r.Amount) as Budget
FROM ProjectStaffing ps
INNER JOIN Rate r on (r.ProviderId = ps.ProviderId AND r.OrganizationId = ps.OrganizationId AND r.RoleId = ps.RoleId)
INNER JOIN TimeBudget tb on (tb.ProjectStaffingId = ps.Id)
WHERE ps.ProjectId = @ProjectId
GROUP BY ps.PersonId

SELECT 
    ps.PersonId, 
    SUM(ta.Hours * r.Amount) as Actual
FROM ProjectStaffing ps
INNER JOIN Rate r on (r.ProviderId = ps.ProviderId AND r.OrganizationId = ps.OrganizationId AND r.RoleId = ps.RoleId)
INNER JOIN TimeActual ta on (ta.ProjectStaffingId = ps.Id)
WHERE ps.ProjectId = @ProjectId
GROUP BY ps.PersonId

我尝试了这个,但只是得到了奇怪的结果

SELECT 
    PS.PersonId, 
    SUM(TF.Hours * r.Amount) as Forecast,
    SUM(TB.Hours * r.Amount) as Budget,
    SUM(TA.Hours * r.Amount) as Actual
FROM ProjectStaffing PS
INNER JOIN Rate r on (r.ProviderId = PS.ProviderId AND r.OrganizationId = PS.OrganizationId AND r.RoleId = PS.RoleId)
LEFT JOIN TimeForecast TF on (TF.ProjectStaffingId = PS.Id)
LEFT JOIN TimeBudget TB   on (TB.ProjectStaffingId = PS.Id)
LEFT JOIN TimeActual TA   on (TA.ProjectStaffingId = PS.Id)
WHERE PS.ProjectId = @ProjectId
    AND TF.Hours is not null
GROUP BY PS.PersonId

2 个答案:

答案 0 :(得分:2)

一种直截了当的方法是使用Common Table Expressions

如果所有三个子查询都有每个PersonId的行,那么您可以按任意顺序INNER JOIN。如果其中一个子查询没有所有PersonIds的行,那么LEFT JOIN就可以了。

WITH CTE_Forecast AS
(
    SELECT 
        ps.PersonId, 
        SUM(TF.Hours * r.Amount) as Forecast
    FROM 
        ProjectStaffing ps
    INNER JOIN 
        Rate r ON (r.ProviderId = ps.ProviderId 
                   AND r.OrganizationId = ps.OrganizationId 
                   AND r.RoleId = ps.RoleId)
    INNER JOIN 
        TimeForecast TF on (TF.ProjectStaffingId = ps.Id)
    WHERE 
        ps.ProjectId = @ProjectId
    GROUP BY 
        ps.PersonId
)
, CTE_Budget AS
(
    SELECT 
        ps.PersonId, 
        SUM(tb.Hours * r.Amount) as Budget
    FROM 
        ProjectStaffing ps
    INNER JOIN 
        Rate r ON (r.ProviderId = ps.ProviderId 
                   AND r.OrganizationId = ps.OrganizationId 
                   AND r.RoleId = ps.RoleId)
    INNER JOIN 
        TimeBudget tb on (tb.ProjectStaffingId = ps.Id)
    WHERE 
        ps.ProjectId = @ProjectId
    GROUP BY 
        ps.PersonId
)
, CTE_Actual AS
(
    SELECT 
        ps.PersonId, 
        SUM(ta.Hours * r.Amount) as Actual
    FROM 
        ProjectStaffing ps
    INNER JOIN 
        Rate r ON (r.ProviderId = ps.ProviderId 
                   AND r.OrganizationId = ps.OrganizationId 
                   AND r.RoleId = ps.RoleId)
    INNER JOIN 
        TimeActual ta on (ta.ProjectStaffingId = ps.Id)
    WHERE 
        ps.ProjectId = @ProjectId
    GROUP BY 
        ps.PersonId
)
SELECT
    CTE_Forecast.PersonId,
    CTE_Forecast.Forecast,
    CTE_Budget.Budget, 
    CTE_Actual.Actual
FROM
    CTE_Forecast
INNER JOIN 
    CTE_Budget ON CTE_Budget.PersonId = CTE_Forecast.PersonId
INNER JOIN 
    CTE_Actual ON CTE_Actual.PersonId = CTE_Forecast.PersonId
;

答案 1 :(得分:0)

我发现这可以胜任。但它太复杂了。应该有一个更简单的方法。

SELECT *
FROM
(
    SELECT 
        --ps.PersonId, 
        'FORECAST' AS Description,
        SUM(TF.Hours * r.Amount) as Total --Forecast
    FROM ProjectStaffing ps
    INNER JOIN Rate r on (r.ProviderId = ps.ProviderId AND r.OrganizationId = ps.OrganizationId AND r.RoleId = ps.RoleId)
    INNER JOIN TimeForecast TF on (TF.ProjectStaffingId = ps.Id)
    WHERE ps.ProjectId = @ProjectId
    --GROUP BY ps.PersonId

    UNION ALL

    SELECT 
        --ps.PersonId, 
        'BUDGET' AS Description,
        SUM(tb.Hours * r.Amount) as Total --Budget
    FROM ProjectStaffing ps
    INNER JOIN Rate r on (r.ProviderId = ps.ProviderId AND r.OrganizationId = ps.OrganizationId AND r.RoleId = ps.RoleId)
    INNER JOIN TimeBudget tb on (tb.ProjectStaffingId = ps.Id)
    WHERE ps.ProjectId = @ProjectId
    --GROUP BY ps.PersonId

    UNION ALL

    SELECT 
        --ps.PersonId, 
        'ACTUAL' AS Description,
        SUM(ta.Hours * r.Amount) as Total --Actual
    FROM ProjectStaffing ps
    INNER JOIN Rate r on (r.ProviderId = ps.ProviderId AND r.OrganizationId = ps.OrganizationId AND r.RoleId = ps.RoleId)
    INNER JOIN TimeActual ta on (ta.ProjectStaffingId = ps.Id)
    WHERE ps.ProjectId = @ProjectId
    --GROUP BY ps.PersonId
) p
PIVOT (SUM(p.Total) FOR [Description] in ([FORECAST], [BUDGET], [ACTUAL]) ) AS pvt