【问题标题】:Multiple Left Join with sum多个左连接与总和
【发布时间】:2015-04-04 10:56:25
【问题描述】:

我正在尝试在 sql 查询中使用 Left Join 显示来自 3 个表的总和的表(带有数据表插件)信息。 我使用以下查询成功地编辑了服务器端查询并显示了两个表之间的第一个关节(t1=...budget & t2=..budget_changes)的正确数据:

$year=date('Y');

$sQuery = "SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ", implode(", ", $aColumns)).", 

IFNULL(SUM(t2.change_amount),0) AS operation_changes,
(t1.operation_BP+IFNULL(SUM(t2.change_amount),0)) AS operation_total 
FROM budget AS t1 

LEFT JOIN wp_dri_budget_changes AS t2 ON t2.change_year_operation=t1.operation_year_number 

WHERE t1.operation_year=".$year." AND t1.operation_active=1 $sWhere

GROUP BY operation_year_number, change_year_operation $sOrder $sLimit";

但是当我尝试使用左联合查询连接 3 个表时,总和结果是错误的。

$year=date('Y');

$sQuery = "SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ", implode(", ", $aColumns)).",

IFNULL(SUM(t2.change_amount),0) AS operation_changes,

(t1.operation_BP+IFNULL(SUM(t2.change_amount),0)) AS operation_total,

IFNULL(SUM(t3.expense_enga_amount),0) AS operation_consommation

FROM budget AS t1

LEFT JOIN wp_dri_budget_changes AS t2 ON t2.change_year_operation=t1.operation_year_number

LEFT JOIN wp_dri_budget_expenses AS t3 ON t3.expense_year_operation=t1.operation_year_number 

WHERE t1.operation_year=".$year." AND t1.operation_active=1 $sWhere GROUP BY operation_year_number, change_year_operation, expense_year_operation $sOrder $sLimit";

这个查询有什么问题?非常感谢 MT

【问题讨论】:

  • 发布一些输入数据和预期结果。
  • 向我们展示表格结构
  • 请合理格式化代码。请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出您可以给出的最少代码,即您显示的代码可以通过您显示的代码扩展为不正常。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。 How to Ask

标签: php mysql sql sum left-join


【解决方案1】:

这是最终结果,似乎有效。

$year=date('Y');
$sQuery = "SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ", implode(", ", $aColumns)).", 
t2.total_changes,
t1.operation_BP+IFNULL(total_changes,0) AS operation_total, 
t3.total_conso
FROM $sTable AS t1
LEFT JOIN (SELECT tt2.change_year_operation, IFNULL(SUM(tt2.change_amount),0) AS total_changes FROM wp_dri_budget_changes tt2 GROUP BY tt2.change_year_operation) t2 ON t1.operation_year_number = t2.change_year_operation
LEFT JOIN (SELECT tt3.expense_year_operation, IFNULL(SUM(tt3.expense_enga_amount),0) AS total_conso FROM wp_dri_budget_expenses tt3 GROUP BY tt3.expense_year_operation) AS t3 ON t1.operation_year_number = t3.expense_year_operation
WHERE t1.operation_year=".$year." AND t1.operation_active=1 $sWhere $sOrder $sLimit";

OPERATION_NUMBER 名称 BP 更改 TOTAL TOTAL_CONSO


15P731OV001 project1 28000(空)28000(空)

13P0012OV001 项目2 612500 -60000 552500 21000

**但是现在 IFNULL(x,0) 似乎不再起作用,并且当总和结果为 NULL 时显示 null(数据表中的 NaN.N)**

【讨论】:

    【解决方案2】:

    问题可能是由于您的数据和求和正在进行的笛卡尔结果。澄清一下,这里是一个简单的查询...我知道我没有全部,也没有完美的连接列,这只是为了澄清。

    另外,我知道我已经缩写了列和别名,以便于阅读和理解您可能遇到的概念。

    Select
          t1.yr,
          sum( t2.Amt ) as AmtChange
       FROM 
          budget AS t1
             LEFT JOIN Budget_Changes AS t2
                on t1.yr = t2.Yr
    

    最后,没问题...对于给定的年份,您将从第二张表中获得总数。表2中有很多记录。例如:数据

    Budget
    Yr
    2013
    2014
    
    Budget_Changes
    Yr    Amt
    2013  10
    2013  20
    2013  30
    2014  40
    2014  50
    
    Your results would be
    Yr    AmtChange
    2013  60
    2014  90
    

    在这一点上我们可能同意...现在,输入另一个每年(或其他)的表,该表每年也有多个记录...

    Change_Orders
    Yr     COAmt
    2013   100
    2013   120
    2014   200
    2014   220
    

    然后您将其添加为查询的辅助左连接,例如

    Select
          t1.yr,
          sum( t2.Amt ) as AmtChange,
          sum( t3.COAmt ) as COAmtChange
       FROM 
          budget AS t1
             LEFT JOIN Budget_Changes AS t2
                on t1.yr = t2.Yr
             LEFT JOIN Change_Orders AS t3
                on t1.yr = t3.Yr
    
    
    Your might expect the results to be
    Yr    AmtChange  COChangeAmt
    2013  60         220
    2014  90         420
    

    但是,由于它是笛卡尔结果...每个连接多行正在获取结果 TIMES 每个存在于另一个表中的条目...类似于

    Yr    AmtChange  COChangeAmt
    2013  120         440
    2014  180         840
    

    要解决此问题,您从中获取小计的每个单独的表都应单独处理,并按其自己的年份分组,以便子集在每个数据上下文中仅返回一行。类似的东西

    Select
          t1.yr,
          t2.AmtChange,
          t3.COAmtChange
       FROM 
          budget AS t1
             LEFT JOIN ( select BC.Yr, sum( BC.Amt ) as AmtChange
                            from Budget_Changes BC
                            group by BC.Yr ) t2
                on t1.yr = t2.Yr
             LEFT JOIN ( select CO.Yr, sum( CO.COAmt ) as COAmtChange
                            from Change_Orders CO
                            group by CO.Yr ) AS t3
                on t1.yr = t3.Yr
    

    因此,每个子查询将仅返回 1 条记录用于汇总的相应年份,从而防止 sum() 金额重复。

    【讨论】:

    • 感谢您的帮助 DRapp!
      感谢 axiac 和 Kim Alexander 提议帮助我。
    • @maxenceT,很高兴为您提供帮助,并希望此基础能够帮助您解决问题。另外,作为新手(我们都去过那里),请查看链接以获取帮助 -> 了解网站礼仪。
    猜你喜欢
    • 2019-05-19
    • 1970-01-01
    • 2012-09-12
    • 2020-07-28
    • 2016-08-24
    • 2019-06-23
    • 2019-09-03
    • 1970-01-01
    • 2022-10-01
    相关资源
    最近更新 更多