【问题标题】:How to join two tables and then display the sum value of each data of a table gathering from the other table如何连接两个表,然后显示从另一个表收集的表的每个数据的总和值
【发布时间】:2011-12-27 13:25:04
【问题描述】:

首先抱歉,如果我的问题标题听起来很愚蠢......我有以下表格。第一个表包含我的费用类型的名称,第二个表包含这些费用的金额和日期信息。如果您注意到下面的第二个表,则有一个名为“e_id”的字段,它是第一个表中我的费用的相应 id 值。

第一个表名:expense_type

  id     expense_name 

  1        Insurance
  2        Interest Payment
  3        Rent
  4        Electricity

 ... and goes on like this (unlimited perhaps :))

第二个表名:expense_details

 id       e_id    amount       date

  1        3      1000        2011-12-11 
  2        1       500        2011-12-19 
  3        4        10        2011-11-21
  4        3      1000        2012-01-12

... and goes on like this )

现在我的计划是从这两个表中获取所有值并生成如下结果。但由于第一个表有未知数量的信息(对我来说)我不知道如何编写查询(php 和 mysql)来生成这样的结果。

请您帮助我了解如何实现这一目标?

在此先感谢 :)

P.S 仅供参考,我正在使用 Codeigniter。

                                 **For the Month: January 2011**


           Insurance    :  1000

           Rent         :  3453

           Electricity  :   546

      Interest Payment  :   546    
  ---------------------------------
      **Total Expenses**: 938949 /// this value is just for an example

【问题讨论】:

    标签: php mysql codeigniter codeigniter-2


    【解决方案1】:

    你可以使用

    SELECT expense_name, SUM(amount) as monthly_total
    FROM expense_details, expense_type
    WHERE expense_type.id=expense_details.e_id
      AND `date` >= '2011-01-01' 
      AND `date` <  '2011-02-01'  
    GROUP BY expense_details.e_id;
    

    然后根据需要进行格式化。注意date 是反引号,因为它也是 MySQL 中的一个函数。

    要更改月份,您只需执行 `date >= 'yyyy-mm-01' AND date (unlessmm` 是十二月...)。

    你也可以这样做

    WHERE MONTH(`date`)=1 AND YEAR(`date`)=2011, 
    

    WHERE `date`>='yyyy-mm-dd' AND `date`<DATE_ADD('yyyy-mm-dd',INTERVAL 1 MONTH)
    

    对于 2011 年 1 月(看看 here),但我认为如果您没有日期索引,它会有点慢(当然,您选择哪种方法取决于您要筛选的预期记录数,数据库是如何设置的,等等——但为什么不试一试,看看哪个版本适合你?)

    【讨论】:

    • 非常感谢 math.coffee。虽然我没有测试过你的代码,但是看着它我想它会起作用,你只是让它变得简单。但是我对显示值有疑问...因为我想显示每个费用的总和和费用名称..我应该只回显费用名称和每月总计吗?谢谢:)
    • 是的,没错。您可以调整@phirshybar 的答案:$data = $this-&gt;db-&gt;query($sql)-&gt;result_array();,然后循环通过foreach ($data as $item),您将需要$item['expense_name]$item['monthly_total']
    【解决方案2】:

    您可以在控制器或模型中执行此操作:

    $sql = "SELECT a.*, b.expense_name FROM expense_details AS a, expense_name AS b WHERE a.e_id = b.id ORDER BY a.id ASC";
    $data = $this->db->query($sql)->result_array();
    $totals = array();
    
    echo '**For the Month: January 2011**';
    echo "\n\n";
    
    foreach ($data as $item){
      $totals[$item['expense_name']] = isset($totals[$item['expense_name']]) ? $totals[$item['expense_name']] + $item['amount'] : $item['amount']: 
    }
    
    foreach ($totals as $name => $val){
      echo $name.': '.$val;
      echo "\n\n";
    }
    

    不是最优雅或最稳定的方法,但我希望这可以帮助您了解您需要做什么。我想您可能还想按月分解总数。

    【讨论】:

    • 这个是按月搜索吗?
    • 不,这只是为了开始。您可以在 SELECT 子句中添加“...MONTH(a.date) AS month, YEAR(a.date) AS year...”。然后使用 $item['year'].'-'.$item['month'] 作为 $totals 数组中的键。
    【解决方案3】:
    SELECT ed.e_id, DATE_FORMAT(ed.date, '%M %Y') AS `month`, et.expense_name, SUM(ed.amount) AS `amount`
    FROM expense_details ed
      INNER JOIN expense_types et ON (et.id = ed.e_id)
    WHERE (ed.date BETWEEN '2011-11-01' AND DATE_ADD('2011-11-01', INTERVAL 3 MONTH))
    GROUP BY `month`, ed.e_id
    WITH ROLLUP
    

    当然,您可以设置任何日期范围,甚至可能是一个月,或者根本没有日期条件,以获得完整的报告。 它将每月汇总每种类型的费用(您将填写 monthed.e_id = NULL - 这样您就知道它是当月的总和),然后是全职(monthed.e_id = 空)。

    输出将是这样的:

    e_id    month           expense_name    amount  
    1       December 2011   Insurance       500
    3       December 2011   Rent            1000
    NULL    December 2011   Rent            1500
    3       January 2012    Rent            1000
    NULL    January 2012    Rent            1000
    4       November 2011   Electricity     10
    NULL    November 2011   Electricity     10
    NULL    NULL            Electricity     2510
    

    当然当你看到e_id = NULL 时你必须忽略sticky expense_name

    有些人可能会建议您只获得结果,然后用 PHP 将它们求和,但对于大型报告来说,这会消耗性能。让 SQL 做它最擅长的事情(挖掘数据计数、求和等等),让 PHP 做它最擅长的事情(渲染 HTML)。

    当然,如果您正确设置了外键(这就是为什么 JOIN 会比从两个表中选择并在 WHERE 子句中添加 id=e_id 更快)并且将 date 字段编入索引,那么 SQl 将奖励您甚至更好的性能.

    【讨论】:

    • 您可能实际遇到的唯一问题 - 当您有 WITH ROLLUP 修饰符时,您不能使用 ORDER BY。如果它很重要,您仍然可以在GROUP BY 字段中使用ASC/DESC,并且要正确按日期排序,您必须使用GROUP BY STR_TO_DATE(`month`,'%M %Y') ASC, ed.e_id WITH ROLLUP 将其转换回日期
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-15
    • 2020-05-23
    • 1970-01-01
    • 2017-06-11
    • 1970-01-01
    • 1970-01-01
    • 2011-12-27
    相关资源
    最近更新 更多