CREATE OR ALTER VIEW [dbo].[Prj_V_BudgetMonthly] AS WITH base AS ( SELECT x.[TenantId], p.[BranchId], w.[ProjectId], x.[ResourceType], x.[Kind], ISNULL(x.[Cost], 0) AS [Cost], DATEFROMPARTS(YEAR(COALESCE(x.[DocumentDate], w.[StartDate])), MONTH(COALESCE(x.[DocumentDate], w.[StartDate])), 1) AS [PeriodDate] FROM [dbo].[Prj_T_WorkPackageResource] x INNER JOIN [dbo].[Prj_T_WorkPackage] w ON w.[Id] = x.[WorkPackageId] AND w.[IsDeleted] = 0 INNER JOIN [dbo].[Prj_T_Project] p ON p.[Id] = w.[ProjectId] AND p.[IsDeleted] = 0 WHERE x.[IsDeleted] = 0 ), monthly AS ( SELECT [TenantId], [BranchId], [ProjectId], [ResourceType], [PeriodDate], SUM(CASE WHEN [Kind] = 'Planned' THEN [Cost] ELSE 0 END) AS [Planned], SUM(CASE WHEN [Kind] = 'Actual' THEN [Cost] ELSE 0 END) AS [Actual] FROM base GROUP BY [TenantId], [BranchId], [ProjectId], [ResourceType], [PeriodDate] ) SELECT CAST(CONCAT(CAST(m.[ProjectId] AS nvarchar(36)), '|', m.[ResourceType]) AS nvarchar(120)) AS [Id], CAST(NULL AS nvarchar(120)) AS [ParentId], m.[TenantId], m.[ProjectId], m.[ResourceType], CAST(0 AS bit) AS [IsDeleted], 1 AS [RowLevel], CAST(m.[ResourceType] AS nvarchar(64)) AS [Title], MIN(m.[PeriodDate]) AS [StartDate], EOMONTH(MAX(m.[PeriodDate])) AS [EndDate], CAST(NULL AS int) AS [Year], CAST(NULL AS int) AS [Month], CAST(SUM(m.[Planned]) AS decimal(18, 4)) AS [Planned], CAST(SUM(m.[Actual]) AS decimal(18, 4)) AS [Actual], CAST(CASE WHEN SUM(m.[Planned]) > 0 THEN SUM(m.[Actual]) * 100.0 / SUM(m.[Planned]) ELSE 0 END AS decimal(18, 4)) AS [Ratio], CAST(CASE WHEN SUM(m.[Planned]) > 0 THEN CASE WHEN SUM(m.[Actual]) * 100.0 / SUM(m.[Planned]) > 100 THEN 100 ELSE SUM(m.[Actual]) * 100.0 / SUM(m.[Planned]) END ELSE 0 END AS decimal(18, 4)) AS [Progress], m.[BranchId] FROM monthly m GROUP BY m.[TenantId], m.[BranchId], m.[ProjectId], m.[ResourceType] UNION ALL SELECT CAST(CONCAT(CAST(m.[ProjectId] AS nvarchar(36)), '|', m.[ResourceType], '|', FORMAT(m.[PeriodDate], 'yyyy-MM')) AS nvarchar(120)), CAST(CONCAT(CAST(m.[ProjectId] AS nvarchar(36)), '|', m.[ResourceType]) AS nvarchar(120)), m.[TenantId], m.[ProjectId], m.[ResourceType], CAST(0 AS bit), 2, CAST(FORMAT(m.[PeriodDate], 'yyyy-MM') AS nvarchar(64)), m.[PeriodDate], EOMONTH(m.[PeriodDate]), YEAR(m.[PeriodDate]), MONTH(m.[PeriodDate]), CAST(m.[Planned] AS decimal(18, 4)), CAST(m.[Actual] AS decimal(18, 4)), CAST(CASE WHEN m.[Planned] > 0 THEN m.[Actual] * 100.0 / m.[Planned] ELSE 0 END AS decimal(18, 4)), CAST(CASE WHEN m.[Planned] > 0 THEN CASE WHEN m.[Actual] * 100.0 / m.[Planned] > 100 THEN 100 ELSE m.[Actual] * 100.0 / m.[Planned] END ELSE 0 END AS decimal(18, 4)), m.[BranchId] FROM monthly m GO