CREATE OR REPLACE VIEW public."Prj_V_BudgetMonthly" AS WITH base AS ( SELECT x."TenantId", p."BranchId", w."ProjectId", x."ResourceType", x."Kind", COALESCE(x."Cost", 0) AS "Cost", date_trunc('month', COALESCE(x."DocumentDate", w."StartDate"))::date AS "PeriodDate" FROM public."Prj_T_WorkPackageResource" x INNER JOIN public."Prj_T_WorkPackage" w ON w."Id" = x."WorkPackageId" AND w."IsDeleted" = FALSE INNER JOIN public."Prj_T_Project" p ON p."Id" = w."ProjectId" AND p."IsDeleted" = FALSE WHERE x."IsDeleted" = FALSE ), 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 (m."ProjectId"::text || '|' || m."ResourceType")::varchar(120) AS "Id", NULL::varchar(120) AS "ParentId", m."TenantId", m."ProjectId", m."ResourceType", FALSE AS "IsDeleted", 1 AS "RowLevel", m."ResourceType"::varchar(64) AS "Title", MIN(m."PeriodDate") AS "StartDate", (MAX(m."PeriodDate") + INTERVAL '1 month' - INTERVAL '1 day')::date AS "EndDate", NULL::integer AS "Year", NULL::integer AS "Month", SUM(m."Planned")::numeric(18,4) AS "Planned", SUM(m."Actual")::numeric(18,4) AS "Actual", (CASE WHEN SUM(m."Planned") > 0 THEN SUM(m."Actual") * 100.0 / SUM(m."Planned") ELSE 0 END)::numeric(18,4) AS "Ratio", (CASE WHEN SUM(m."Planned") > 0 THEN LEAST(SUM(m."Actual") * 100.0 / SUM(m."Planned"), 100) ELSE 0 END)::numeric(18,4) AS "Progress", m."BranchId" FROM monthly m GROUP BY m."TenantId", m."BranchId", m."ProjectId", m."ResourceType" UNION ALL SELECT (m."ProjectId"::text || '|' || m."ResourceType" || '|' || to_char(m."PeriodDate", 'YYYY-MM'))::varchar(120), (m."ProjectId"::text || '|' || m."ResourceType")::varchar(120), m."TenantId", m."ProjectId", m."ResourceType", FALSE, 2, to_char(m."PeriodDate", 'YYYY-MM')::varchar(64), m."PeriodDate", (m."PeriodDate" + INTERVAL '1 month' - INTERVAL '1 day')::date, EXTRACT(YEAR FROM m."PeriodDate")::integer, EXTRACT(MONTH FROM m."PeriodDate")::integer, m."Planned"::numeric(18,4), m."Actual"::numeric(18,4), (CASE WHEN m."Planned" > 0 THEN m."Actual" * 100.0 / m."Planned" ELSE 0 END)::numeric(18,4), (CASE WHEN m."Planned" > 0 THEN LEAST(m."Actual" * 100.0 / m."Planned", 100) ELSE 0 END)::numeric(18,4), m."BranchId" FROM monthly m;