PHP는 월을 기준으로 행을 읽습니다.

Aug 27 2020

이것은 내 테이블의 모양입니다 (이것은 단지 예이며 내 테이블에는 엄청난 양의 행이 포함되어 있습니다).

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은 1 월이 아닌 8 월에 전송 날짜가 있으므로 모든 셀의 값은 0이어야하지만 8 월은 12750이어야합니다)

답변

1 user3783243 Aug 27 2020 at 12:04

반환 된 값을 확인하지 않습니다. 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'];

선택을 반복하는 동안.

1 O.Jones Aug 27 2020 at 11:47

SQL 은 데이터 행 세트 를 처리 합니다 . 샘플 데이터와 쿼리는 두 행의 데이터 세트를 생성합니다. 그리고 PHP 코드는 해당 세트를 읽고 세트의 <td>nnn</td>각 행에 대해 HTML 테이블 열을 생성합니다 . 그 중 두 개뿐입니다. 따라서 HTML 테이블에는 두 개의 열만 있습니다. 그것이 당신의 코드가 당신이 원하는 것을하지 않는 이유 입니다. 이 db-fiddle.https://www.db-fiddle.com/f/nfv5wDnBWWgP8dq8E26QtZ/0 보여줍니다.

더 흥미로운 질문 : 어떻게 작동 시키나요? 익숙해지기 전까지는 놀랍도록 까다 롭습니다. 다양한 솔루션이 있습니다. 내가 가장 좋아하는 것은 원하는 12 개의 행 집합을 생성하는 쿼리를 사용한 다음 실제 데이터를 해당 집합에 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 변형을 사용하는 경우 해당 신비한 테이블 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))결과 집합이 누락 된 달의 데이터에 대해 null 대신 0을 표시하도록합니다. 보고서가 좀 더 깔끔해집니다.
  • EXPANDED 당신은 둘 필요가 YEAR(transfer) = YEAR(CURRENT_DATE())에 ON당신의 절 LEFT JOIN보다는에있는 WHERE절. 왜? WHERE 절 (또는 ORDER BY 또는 GROUP BY 절)이 LEFT JOINed 테이블의 열을 언급하면 ​​LEFT JOIN을 일반 내부 JOIN으로 변환합니다. 내부 JOIN 연산은 JOIN의 오른쪽에서 행을 억제합니다. LEFT JOIN은 그들을 보존합니다.
  • 당신 GROUP BY과 ORDER BY당신의 순서 값.

얼마 전에 이것에 대한 기사를 썼습니다 .

1 FlashThunder Aug 27 2020 at 12:15

다음과 같이 시도하십시오 (조금 더 깨끗하고 이해하기 쉬운 솔루션).

<?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>