我使用下面的代码从其他表中计算所需的信息。我使用联接来显示名称而不是ID,并从其他表中获取所需的总和。我使用COALESCE
将null转换为零。
如果我需要加总COALESCED值,就不得不再次使用它,上面的代码很难理解,而且由于需要添加更多信息而变得越来越困难,这只是主项目的一小部分,因此真的很难使用它,并且会有很多错误和错误。
它必须是如此复杂吗?还是我做错了?如果必须这样复杂,是否有任何替代方法可以通过更简单的方法和代码来获得相同的结果?另一个RDBMS还是其他?
SELECT P.PROJ_ID, P.PROJ_STATUS, P.TYPE_ID, PT.TYPE_NAME, P.CLASS_ID, CLA.CLASS_NAME, P.PROJ_NO, P.PROJ_YEAR, P.PROJ_NAME, P.OLD_PROJ_NAME,
P.AGENCY_ID, A.AGENCY_NAME, P.CONTRACT_NO, P.CONTRACT_DATE, P.MINISTRY_ID, M.MINISTRY_NAME,
P.DIRECTORATE_ID, DIR.DIRECTORATE_NAME,
P.COST, P.ESTIMATED_COST, COALESCE(CO.ADDED_COSTS, 0) AS ADDED_COSTS, (COALESCE(P.COST, 0) + COALESCE(CO.ADDED_COSTS, 0)) AS TOTAL_COST,
P.ALLOCATION,
COALESCE(EPY.PAST_YEARS, 0) AS PAST_YEARS,
COALESCE(EF.PAST_MONTHS, 0) AS PAST_MONTHS,
COALESCE(ECM.CURRENT_MONTH, 0) AS CURRENT_MONTH,
COALESCE(ECY.CURRENT_YEAR, 0) AS CURRENT_YEAR,
COALESCE(E.TOTAL_EXPENSES, 0) AS TOTAL_EXPENSES,
COALESCE(CASH_EPY.CASH_PAST_YEARS, 0) AS CASH_PAST_YEARS,
COALESCE(CASH_EF.CASH_PAST_MONTHS, 0) AS CASH_PAST_MONTHS,
COALESCE(CASH_ECM.CASH_CURRENT_MONTH, 0) AS CASH_CURRENT_MONTH,
COALESCE(CASH_ECY.CASH_CURRENT_YEAR, 0) AS CASH_CURRENT_YEAR,
COALESCE(CASH_E.CASH_TOTAL_EXPENSES, 0) AS CASH_TOTAL_EXPENSES,
COALESCE(TOTAL_E.TOTAL_EXPENSES_CASH, 0) AS TOTAL_EXPENSES_CASH,
((COALESCE(P.COST, 0) + COALESCE(CO.ADDED_COSTS, 0)) - COALESCE(E.TOTAL_EXPENSES, 0)) AS REMAINING,
P.DURATION, COALESCE(DU.ADDED_DURATIONS, 0) AS ADDED_DURATIONS,
(COALESCE(P.DURATION, 0) + COALESCE(DU.ADDED_DURATIONS, 0)) AS TOTAL_DURATION, P.START_DATE, P.FINISH_DATE,
P.GOVERNORATE_ID, G.GOVERNORATE_NAME, P.PROVINCE_ID, PR.PROVINCE_NAME, P.DISTRICT_ID, D.DISTRICT_NAME,
P.TOWN_ID, T.TOWN_NAME,
COALESCE( (E.TOTAL_EXPENSES / (COALESCE(P.COST, 0) + COALESCE(CO.ADDED_COSTS, 0)))/100, 0) AS FINANCIAL_ACHIEVEMENT,
P.MATERIAL_ACHIEVEMENT, P.NOTES
FROM PROJECTS P
INNER JOIN PROJECTS_TYPES PT
ON P.TYPE_ID = PT.TYPE_ID
INNER JOIN CLASSES CLA
ON P.CLASS_ID = CLA.CLASS_ID
INNER JOIN AGENCIES A
ON P.AGENCY_ID = A.AGENCY_ID
LEFT JOIN MINISTRIES M
ON P.MINISTRY_ID = M.MINISTRY_ID
LEFT JOIN DIRECTORATES DIR
ON P.DIRECTORATE_ID = DIR.DIRECTORATE_ID
INNER JOIN GOVERNORATES G
ON P.GOVERNORATE_ID = G.GOVERNORATE_ID
LEFT JOIN PROVINCES PR
ON P.PROVINCE_ID = PR.PROVINCE_ID
LEFT JOIN DISTRICTS D
ON P.DISTRICT_ID = D.DISTRICT_ID
LEFT JOIN TOWNS T
ON P.TOWN_ID = T.TOWN_ID
-- ADDED COSTS
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(ADDED_VALUE, 0) - COALESCE(REMOVED_VALUE, 0)) as ADDED_COSTS
FROM COSTS
GROUP BY PROJ_ID ) AS CO
ON P.PROJ_ID = CO.PROJ_ID
-- EXPENSES FROM PAST YEARS
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as PAST_YEARS
FROM EXPENSES WHERE EXTRACT(YEAR FROM DOC_DATE) < EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = FALSE
GROUP BY PROJ_ID ) AS EPY
ON P.PROJ_ID= EPY.PROJ_ID
-- EXPENSES FROM PAST MONTHS IN CUREENT YEAR
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as PAST_MONTHS
FROM EXPENSES WHERE EXTRACT(MONTH FROM DOC_DATE) < EXTRACT(MONTH FROM CURRENT_DATE)
AND EXTRACT(YEAR FROM DOC_DATE) = EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = FALSE
GROUP BY PROJ_ID ) AS EF
ON P.PROJ_ID= EF.PROJ_ID
-- EXPENSES FROM CURRENT MONTH AND YEAR
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as CURRENT_MONTH
FROM EXPENSES WHERE EXTRACT(MONTH FROM DOC_DATE) = EXTRACT(MONTH FROM CURRENT_DATE) AND EXTRACT(YEAR FROM DOC_DATE) = EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = FALSE
GROUP BY PROJ_ID ) AS ECM
ON P.PROJ_ID= ECM.PROJ_ID
-- SUM OF EXPENSES IN CURRENT YEAR
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as CURRENT_YEAR
FROM EXPENSES WHERE EXTRACT(YEAR FROM DOC_DATE) = EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = FALSE
GROUP BY PROJ_ID ) AS ECY
ON P.PROJ_ID= ECY.PROJ_ID
-- TOTAL EXPENSES FROM ALL TIME
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as TOTAL_EXPENSES
FROM EXPENSES WHERE CASH_DEDUCTIONS = FALSE
GROUP BY PROJ_ID ) AS E
ON P.PROJ_ID= E.PROJ_ID
-- CASH DEDUCTIONS SUMS
-- CASH DEDUCTIONS FROM PAST YEARS
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as CASH_PAST_YEARS
FROM EXPENSES WHERE EXTRACT(YEAR FROM DOC_DATE) < EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = TRUE
GROUP BY PROJ_ID ) AS CASH_EPY
ON P.PROJ_ID= CASH_EPY.PROJ_ID
-- CASH DEDUCTIONS FROM PAST MONTHS IN CUREENT YEAR
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as CASH_PAST_MONTHS
FROM EXPENSES WHERE EXTRACT(MONTH FROM DOC_DATE) < EXTRACT(MONTH FROM CURRENT_DATE)
AND EXTRACT(YEAR FROM DOC_DATE) = EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = TRUE
GROUP BY PROJ_ID ) AS CASH_EF
ON P.PROJ_ID= CASH_EF.PROJ_ID
-- CASH DEDUCTIONS FROM CURRENT MONTH AND YEAR
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as CASH_CURRENT_MONTH
FROM EXPENSES WHERE EXTRACT(MONTH FROM DOC_DATE) = EXTRACT(MONTH FROM CURRENT_DATE) AND EXTRACT(YEAR FROM DOC_DATE) = EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = TRUE
GROUP BY PROJ_ID ) AS CASH_ECM
ON P.PROJ_ID= CASH_ECM.PROJ_ID
-- SUM OF CASH DEDUCTIONS IN CURRENT YEAR
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as CASH_CURRENT_YEAR
FROM EXPENSES WHERE EXTRACT(YEAR FROM DOC_DATE) = EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = TRUE
GROUP BY PROJ_ID ) AS CASH_ECY
ON P.PROJ_ID= CASH_ECY.PROJ_ID
-- TOTAL CASH DEDUCTIONS FROM ALL TIME
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as CASH_TOTAL_EXPENSES
FROM EXPENSES WHERE CASH_DEDUCTIONS = TRUE
GROUP BY PROJ_ID ) AS CASH_E
ON P.PROJ_ID= CASH_E.PROJ_ID
-- TOTAL EXPENSES AND CASH DEDUCTIONS FROM ALL TIME
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as TOTAL_EXPENSES_CASH
FROM EXPENSES
GROUP BY PROJ_ID ) AS TOTAL_E
ON P.PROJ_ID= TOTAL_E.PROJ_ID
-- ADDED DURATIONS
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(ADDED_VALUE, 0) - COALESCE(REMOVED_VALUE, 0)) as ADDED_DURATIONS
FROM DURATIONS
GROUP BY PROJ_ID ) AS DU
ON P.PROJ_ID= DU.PROJ_ID
ORDER BY P.PROJ_YEAR, P.TYPE_ID, P.PROJ_NO
答案 0 :(得分:0)
我认为从Expenses表上的仅一个子查询开始会是一个很好的选择。看起来您在子查询中的合并只是将0替换为1列上的空值-您可以运行UPDATE来解决此问题,但是如果没有,我在下面的示例中提供了一种仅执行一次的方法。
您有(例如):
-- TOTAL CASH DEDUCTIONS FROM ALL TIME
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as CASH_TOTAL_EXPENSES
FROM EXPENSES WHERE CASH_DEDUCTIONS = TRUE
GROUP BY PROJ_ID ) AS CASH_E
ON P.PROJ_ID= CASH_E.PROJ_ID
-- TOTAL EXPENSES AND CASH DEDUCTIONS FROM ALL TIME
LEFT JOIN (SELECT PROJ_ID, SUM(COALESCE(TOTAL_VALUE, 0)) as TOTAL_EXPENSES_CASH
FROM EXPENSES
GROUP BY PROJ_ID ) AS TOTAL_E
ON P.PROJ_ID= TOTAL_E.PROJ_ID
您可以改为执行以下操作:
with MY_EXPENSES AS
(
select COALESCE(TOTAL_VALUE, 0) as MY_TOTAL_VALUE, exp.*
from EXPENSES),
EXPENSES_SUMMARY AS
(
SELECT PROJ_ID,
sum(case when CASH_DEDUCTIONS = TRUE
then MY_TOTAL_VALUE else 0
end) as CASH_TOTAL_EXPENSES,
sum(MY_TOTAL_VALUE) as TOTAL_EXPENSES_CASH
FROM MY_EXPENSES
GROUP BY PROJ_ID )
<Big Query>
LEFT OUTER JOIN EXPENSES_SUMMARY es P.PROJ_ID= TOTAL_E.PROJ_ID
基本上从子查询的where子句中取出条件,并将它们放在总和内的case语句中-然后,子查询项中可以包含该EXPENSES表中的所有15个项,或者其中有很多项。只需合并一次TOTAL_VALUE,而不是在每个子查询中合并一次。
您还可以创建一个包含摘要数据的视图。
在费用,持续时间或费用中是否根本不存在任何proj_id?如果没有,那么一旦进行了上述更改,就不必在主查询中进行任何COALESCE操作。如果是这样,那么您可能仍需要用0代替一些空值-如果您只是想从查询中合并,可以在客户端执行此操作。
通常,我会找到'with'。 。 。选择>对于复杂查询更具可读性,但这可能只是一个优先选择。
答案 1 :(得分:0)
这是最后一个更快,更干净的代码,这要归功于aduguid和dandarc
WITH
EXPENSES_SUMS
AS
(
SELECT
PROJ_ID
, SUM(CASE
WHEN EXTRACT(YEAR FROM DOC_DATE) < EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = FALSE
THEN TOTAL_VALUE
END) AS PAST_YEARS
, SUM(CASE
WHEN EXTRACT(MONTH FROM DOC_DATE) < EXTRACT(MONTH FROM CURRENT_DATE) AND EXTRACT(YEAR FROM DOC_DATE) = EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = FALSE
THEN TOTAL_VALUE
END) AS PAST_MONTHS
, SUM(CASE
WHEN EXTRACT(MONTH FROM DOC_DATE) = EXTRACT(MONTH FROM CURRENT_DATE) AND EXTRACT(YEAR FROM DOC_DATE) = EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = FALSE
THEN TOTAL_VALUE
END) AS CURRENT_MONTH
, SUM(CASE
WHEN EXTRACT(YEAR FROM DOC_DATE) = EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = FALSE
THEN TOTAL_VALUE
END) AS CURRENT_YEAR
, SUM(CASE
WHEN CASH_DEDUCTIONS = FALSE
THEN TOTAL_VALUE
END) AS TOTAL_EXPENSES
, SUM(CASE
WHEN EXTRACT(YEAR FROM DOC_DATE) < EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = TRUE
THEN TOTAL_VALUE
END) AS CASH_PAST_YEARS
, SUM(CASE
WHEN EXTRACT(MONTH FROM DOC_DATE) < EXTRACT(MONTH FROM CURRENT_DATE) AND EXTRACT(YEAR FROM DOC_DATE) = EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = TRUE
THEN TOTAL_VALUE
END) AS CASH_PAST_MONTHS
, SUM(CASE
WHEN EXTRACT(MONTH FROM DOC_DATE) = EXTRACT(MONTH FROM CURRENT_DATE) AND EXTRACT(YEAR FROM DOC_DATE) = EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = TRUE
THEN TOTAL_VALUE
END) AS CASH_CURRENT_MONTH
, SUM(CASE
WHEN EXTRACT(YEAR FROM DOC_DATE) = EXTRACT(YEAR FROM CURRENT_DATE) AND CASH_DEDUCTIONS = TRUE
THEN TOTAL_VALUE
END) AS CASH_CURRENT_YEAR
, SUM(CASE
WHEN CASH_DEDUCTIONS = TRUE
THEN TOTAL_VALUE
END) AS CASH_TOTAL_EXPENSES
, SUM(TOTAL_VALUE) AS TOTAL_EXPENSES_CASH
--you can add more columns with your conditions here in case expressions
FROM
EXPENSES
GROUP BY
PROJ_ID
)
,
COSTS_SUMS
AS
(
SELECT
PROJ_ID
, SUM(COALESCE(ADDED_VALUE, 0) - COALESCE(REMOVED_VALUE, 0)) AS ADDED_COSTS
--you can add more columns with your conditions here in case expressions
FROM
COSTS
GROUP BY
PROJ_ID
)
,
DURATIONS_SUMS
AS
(
SELECT
PROJ_ID
, SUM(COALESCE(ADDED_VALUE, 0) - COALESCE(REMOVED_VALUE, 0)) AS ADDED_DURATIONS
--you can add more columns with your conditions here in case expressions
FROM
DURATIONS
GROUP BY
PROJ_ID
)
SELECT
P.PROJ_ID
, P.PROJ_STATUS
, P.TYPE_ID
, PT.TYPE_NAME
, P.CLASS_ID
, CLA.CLASS_NAME
, P.PROJ_NO
, P.PROJ_YEAR
, P.PROJ_NAME
, P.OLD_PROJ_NAME
, P.AGENCY_ID
, A.AGENCY_NAME
, P.CONTRACT_NO
, P.CONTRACT_DATE
, P.MINISTRY_ID
, M.MINISTRY_NAME
, P.DIRECTORATE_ID
, DIR.DIRECTORATE_NAME
, P.COST
, P.ESTIMATED_COST
, COALESCE(CO.ADDED_COSTS, 0) AS ADDED_COSTS
, (COALESCE(P.COST, 0) + COALESCE(CO.ADDED_COSTS, 0)) AS TOTAL_COST
, P.ALLOCATION
, COALESCE(ED.PAST_YEARS, 0) AS PAST_YEARS
, COALESCE(ED.PAST_MONTHS, 0) AS PAST_MONTHS
, COALESCE(ED.CURRENT_MONTH, 0) AS CURRENT_MONTH
, COALESCE(ED.CURRENT_YEAR, 0) AS CURRENT_YEAR
, COALESCE(ED.TOTAL_EXPENSES, 0) AS TOTAL_EXPENSES
, COALESCE(ED.CASH_PAST_YEARS, 0) AS CASH_PAST_YEARS
, COALESCE(ED.CASH_PAST_MONTHS, 0) AS CASH_PAST_MONTHS
, COALESCE(ED.CASH_CURRENT_MONTH, 0) AS CASH_CURRENT_MONTH
, COALESCE(ED.CASH_CURRENT_YEAR, 0) AS CASH_CURRENT_YEAR
, COALESCE(ED.CASH_TOTAL_EXPENSES, 0) AS CASH_TOTAL_EXPENSES
, COALESCE(ED.TOTAL_EXPENSES_CASH, 0) AS TOTAL_EXPENSES_CASH
, ((COALESCE(P.COST, 0) + COALESCE(CO.ADDED_COSTS, 0)) - COALESCE(ED.TOTAL_EXPENSES, 0)) AS REMAINING
, P.DURATION
, COALESCE(DU.ADDED_DURATIONS, 0) AS ADDED_DURATIONS
, (COALESCE(P.DURATION, 0) + COALESCE(DU.ADDED_DURATIONS, 0)) AS TOTAL_DURATION
, P.START_DATE
, P.FINISH_DATE
, P.GOVERNORATE_ID
, G.GOVERNORATE_NAME
, P.PROVINCE_ID
, PR.PROVINCE_NAME
, P.DISTRICT_ID
, D.DISTRICT_NAME
, P.TOWN_ID
, T.TOWN_NAME
, COALESCE( (ED.TOTAL_EXPENSES / (COALESCE(P.COST, 0) + COALESCE(CO.ADDED_COSTS, 0)))/100, 0) AS FINANCIAL_ACHIEVEMENT
, P.MATERIAL_ACHIEVEMENT
, P.NOTES
FROM
PROJECTS P
INNER JOIN PROJECTS_TYPES PT ON P.TYPE_ID = PT.TYPE_ID
INNER JOIN CLASSES CLA ON P.CLASS_ID = CLA.CLASS_ID
INNER JOIN AGENCIES A ON P.AGENCY_ID = A.AGENCY_ID
LEFT JOIN MINISTRIES M ON P.MINISTRY_ID = M.MINISTRY_ID
LEFT JOIN DIRECTORATES DIR ON P.DIRECTORATE_ID = DIR.DIRECTORATE_ID
INNER JOIN GOVERNORATES G ON P.GOVERNORATE_ID = G.GOVERNORATE_ID
LEFT JOIN PROVINCES PR ON P.PROVINCE_ID = PR.PROVINCE_ID
LEFT JOIN DISTRICTS D ON P.DISTRICT_ID = D.DISTRICT_ID
LEFT JOIN TOWNS T ON P.TOWN_ID = T.TOWN_ID
LEFT JOIN EXPENSES_SUMS ED ON P.PROJ_ID = ED.PROJ_ID
LEFT JOIN COSTS_SUMS CO ON P.PROJ_ID = CO.PROJ_ID
LEFT JOIN DURATIONS_SUMS DU ON P.PROJ_ID = CO.PROJ_ID
ORDER BY
P.PROJ_YEAR
, P.TYPE_ID
, P.PROJ_NO