嵌套选择和连接

萨拉芬巴斯

我使用下面的代码从其他表中计算所需的信息。我使用连接来显示名称而不是 ID,并从其他表中获取所需的总和。我曾经COALESCE将空值转换为零。

如果我需要对已经合并的值求和,我不得不再次使用它,上面的代码很难理解,而且越来越难,因为我需要添加更多信息,这只是主项目的一小部分,所以它真的会很难使用它,并且会有很多错误和错误。

有必要这么复杂吗?还是我做错了?如果它必须像这样复杂,是否有任何替代品可以用更简单的方法和代码获得相同的结果?另一个 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 
丹达弧

我认为最好从费用表上的一个子查询开始。看起来您在子查询中的合并只是将 1 列上的空值替换为 0 - 您可以运行 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 在 EXPENSES、DURATION 或 COSTS 中根本不存在?如果没有,那么一旦您进行上述更改,您就不必在主查询中执行任何 COALESCE。如果是这样,那么您可能仍然需要用 0 替换一些空值 - 如果您只想从查询中获得合并,可以在客户端执行。

一般来说,我发现 'with . . . select' 对于复杂查询更具可读性,但这可能只是一种偏好。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

带有嵌套选择和聚合函数的左连接

来自分类Dev

用于嵌套和连接的 Xquery

来自分类Dev

sql嵌套连接内部和左连接

来自分类Dev

SQL嵌套的选择和别名

来自分类Dev

SQL 更新查询嵌套/连接选择

来自分类Dev

SQL连接,选择和位置

来自分类Dev

Rails-建立连接和嵌套表单

来自分类Dev

SASS和数据属性选择和嵌套

来自分类Dev

嵌套选择和DISTINCT / ORDER的性能

来自分类Dev

带有多个连接的嵌套选择语句(MS Access)

来自分类Dev

Ajax连接选择和总记录查询

来自分类Dev

选择计数、内连接和 where 语句

来自分类Dev

选择不存在的地方:多个选择查询和连接查询和连接查询

来自分类Dev

如何在SQLAlchamey中嵌套连接or_和and_

来自分类Dev

子查询中的嵌套连接和关联失败

来自分类Dev

蒸气连接和alsoDecode产生很多嵌套的元组

来自分类Dev

嵌套循环和字符串连接的性能问题

来自分类Dev

PHP和MySQL嵌套数据库连接

来自分类Dev

AWS CLI和JMESPath过滤器并选择嵌套属性

来自分类Dev

在laravel使用join和按月计数嵌套选择

来自分类Dev

从“嵌套”列中选择多个键和值

来自分类Dev

MySQL选择查询和PHP转换为嵌套JSON对象

来自分类Dev

SQL Server:使用别名和嵌套选择无法进行更新

来自分类Dev

如何仅选择和打印嵌套数组的值?

来自分类Dev

BeautifulSoup:从嵌套部分和 div 元素中选择 div

来自分类Dev

Laravel使用不同的连接来插入和选择数据

来自分类Dev

使用XSLT选择和连接特定字符串

来自分类Dev

使用关系和连接选择数据库行

来自分类Dev

如何在链接和边之间进行选择以连接顶点?