【问题标题】:PHP read rows based on monthPHP基于月份读取行
【发布时间】:2020-12-16 06:51:55
【问题描述】:

这就是我的表格的样子(这只是一个示例,我的表格包含大量行):

ID    |          date           |     transfer    |   prov   |
--------------------------------------------------------------
1     |    2020-08-21 14:13:14  |    2020-08-31   |    100   |
2     |    2020-08-21 14:13:14  |    2020-08-31   |    200   |
3     |    2020-08-21 14:13:11  |    2020-07-29   |    100   |
4     |    2020-08-20 13:05:59  |    2020-08-29   |     50   |

这是我的代码:

<table>
          <thead>
              <tr>
                  <th>Januar</th>
                  <th>Februar</th>
                  <th>Mars</th>
                  <th>April</th>
                  <th>Mai</th>
                  <th>Juni</th>
                  <th>Juli</th>
                  <th>August</th>
                  <th>September</th>
                  <th>Oktober</th>
                  <th>November</th>
                  <th>Desember</th>
                </tr>
                  
                  <?php
                  $res = $link -> query("SELECT SUM(prov) as sum 
                        FROM sales 
                        WHERE YEAR(transfer) = YEAR(CURRENT_DATE())
                        GROUP BY MONTH(transfer)
                        ORDER BY MONTH(transfer)"); 
                        
                        echo '<tr>';
                        while( $row = $res->fetch_assoc() ) {
                            echo "<td>$row[sum]</td>";
                        }
                        echo '</tr>';
                  
  ?>
  </thead>
  </table>

所以这基本上应该在 8 月返回 250,在 7 月返回 100,在其余月份返回 0。但是当使用这个时,只有单元格 Januar 和 Februar 显示值,而其他单元格不存在。我做错了什么?

这就是现场的样子: https://ibb.co/8bd6JWP(12750 的转移日期是 8 月,而不是 1 月,所以所有单元格的值都应该是 0,但 8 月应该是 12750)

【问题讨论】:

  • “我做错了什么?” - 您期望您的查询神奇地创建结果行,用于首先不存在的数据。您的表只有 具有 八月和七月的数据,因此您将在此处的结果集中仅获得 两条 记录。 (然后,这些数据会出现在一月和二月的列中,因为它们是 HTML 表中的前两列。)
  • @CBroe 那我该怎么做呢?我尝试添加如下检查:if ($row[sum] == NULL) {,但这给了我错误:Use of undefined constant sum - assumed 'sum'
  • “GROUP BY MONTH(transfer) 不就是这样做的吗?” - 不。它按月分组您的记录,它有与您选择的列或聚合值无关。

标签: php html mysql datetime


【解决方案1】:

您没有检查返回的值。除了聚合值之外,您还需要 select 月份。然后,您可以检查您所在的月份是否是您有值的月份。我会先选择你所有的值,把它们放在一个数组中,然后遍历几个月并检查数组是否有值。

粗略的想法:

$monthdata = array(7 => 10, 8 => 22 );
for($x =1; $x <= date('n'); $x++){
    echo date('F', strtotime('2020-' . $x . '-01')) . PHP_EOL;
    if(!empty($monthdata[$x])) {
        echo $monthdata[$x];
    } else {
        echo 0;
    }
    echo PHP_EOL;
}

并将查询更改为:

SELECT SUM(prov) as sum, MONTH(transfer) as month

所以你可以使用$row['month']$monthdata 应构建为:

$monthdata[$row['month']] = $row['sum'];

在选择迭代期间。

【讨论】:

    【解决方案2】:

    请记住,SQL 处理 sets 数据行。您的示例数据和查询会生成一组两行数据。而且,您的 php 代码读取该集合并为集合中的每一行生成一个&lt;td&gt;nnn&lt;/td&gt; HTML 表格列。只有他们两个。因此,您的 HTML 表格中只有两列。这就是为什么您的代码不能满足您的要求。这个 db-fiddle。 https://www.db-fiddle.com/f/nfv5wDnBWWgP8dq8E26QtZ/0 演示。

    更有趣的问题:如何让它发挥作用?在您习惯之前,这非常棘手。有各种解决方案。我最喜欢的是使用一个查询来生成您想要的十二行集合,然后将您的实际数据 LEFT JOIN 到该集合中。

    MONTH(sometdate) 生成 [1-12] 范围内的整数。因此,如果您可以在查询中使用这 12 个整数的集合,您将得到您想要的。

    试试这个。

                        SELECT SUM(prov) as sum
                        FROM seq_1_to_12
                        LEFT JOIN sales ON seq_1_to_12.seq = MONTH(transfer)
                                       AND YEAR(transfer) = YEAR(CURRENT_DATE())
                        GROUP BY seq_1_to_12.seq
                        ORDER BY seq_1_to_12.seq
    

    如果您使用 MySQL 的 MariaDB 变体,则已经为您定义了 mysterious table seq_1_to_12。万岁。否则,您需要在查询中自己定义它。这是一个好方法。 https://www.db-fiddle.com/f/nfv5wDnBWWgP8dq8E26QtZ/1

        SELECT seq_1_to_12.seq, IFNULL(SUM(prov),0) as sum
        FROM (
               SELECT 1 AS seq UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL 
               SELECT  4 UNION ALL SELECT  5 UNION ALL SELECT  6 UNION ALL
               SELECT  7 UNION ALL SELECT  8 UNION ALL SELECT  9 UNION ALL
               SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12
             ) seq_1_to_12
        LEFT JOIN sales ON seq_1_to_12.seq = MONTH(transfer)
                       AND YEAR(transfer) = YEAR(CURRENT_DATE())
        GROUP BY seq_1_to_12.seq
        ORDER BY seq_1_to_12.seq 
    

    请注意这方面的一些事情。

    • IFNULL(SUM(prov,0)) 使结果集为您丢失的月份数据显示零,而不是空值。它使您的报告更简洁。
    • 扩展您需要将YEAR(transfer) = YEAR(CURRENT_DATE()) 放在ONON 子句中,而不是放在WHERE 子句中。为什么?当 WHERE 子句(或 ORDER BY 或 GROUP BY 子句)提及 LEFT JOINed 表中的列时,它将 LEFT JOIN 转换为普通的内部 JOIN。内部 JOIN 操作从 JOIN 右侧抑制行; LEFT JOIN 保留它们。
    • 您必须GROUP BYORDER BY 您的序列值。

    我不久前写了一个article about this

    【讨论】:

    • 非常好的帖子,感谢您提供的信息(并链接到您的文章)。我快速加起来;是否可以在第一个 Try this: 中也添加这个:FROM sales_gdpr WHERE idid='{$_SESSION['idid']}' AND status='OK'
    • 您可以使用您希望的任何表组合只要您从序列表开始并左连接其余表。有关更多信息,请参阅我关于将过滤条件放在 ON 子句而不是 WHERE 子句中的扩展说明。顺便说一句,在 Stack Overflow 上,习惯上接受解决您的问题的答案并投票支持对您有帮助的答案。为什么?它可以帮助其他用户找到有用的问题和答案。
    • 请看这个:pastebin.com/iJwqk6Pb 诀窍:ON 子句的语法与 WHERE 子句相似。
    【解决方案3】:

    尝试这样的事情(更简洁、更易于理解的解决方案):

    <?php
       $months = array(
              1 => 'Januar',
              2 => 'Februar',
              3 => 'Mars',
              4 => 'April',
              5 => 'Mai',
              6 => 'Juni',
              7 => 'Juli',
              8 => 'August',
              9 => 'September',
              10 => 'Oktober',
              11 => 'November',
              12 => 'Desember');
    ?>
    <table>
              <thead>
                  <tr>
                      <?php
                         foreach($months as $month)
                             echo "<th>$month</th>";
                      ?>
                  </tr>                    
                      <?php
                            $res = $link -> query("SELECT MONTH(transfer) as month, SUM(prov) as sum 
                            FROM sales 
                            WHERE YEAR(transfer) = YEAR(CURRENT_DATE())
                            GROUP BY MONTH(transfer)
                            ORDER BY MONTH(transfer)"); // you don't need to order the results anymore
                            $results = array();
                            while($row = $res->fetch_assoc()){
                                $results[$row['month']] = $row['sum'];
                            }                        
                            echo '<tr>';
                            foreach($months as $m_id => $month){
                                if(isset($results[$m_id]))
                                    echo "<td>".$results[$m_id]."</td>";
                                else
                                    echo "<td>0</td>";
                            }
                            echo '</tr>';
                       ?>
              </thead>
      </table>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多