So this is a how my MySQL table looks like (I have many thousands of rows):
| ID | date | Color | IUSERQ |
| 1 | 2020-09-25 18:55:54 | RED | GGW3 |
| 2 | 2020-09-25 18:24:12 | RED | FFQ3 |
| 3 | 2020-09-24 17:32:52 | RED | GWW3 |
| 4 | 2020-09-23 17:42:37 | BLUE | JJN6 |
| 5 | 2020-09-23 17:33:55 | BLUE | VVV5 |
| 6 | 2020-09-23 18:53:57 | RED | FFQ3 |
| 7 | 2020-09-22 18:15:11 | BLUE | FFQ3 |
Now to count all of the rows and group them in weeks, I do this:
if($stmt = $link->query("SELECT WEEK(date),COUNT(*) FROM sales WHERE color='RED' AND YEAR(date) = YEAR(NOW()) GROUP BY WEEK(date) order by MONTH(date) ASC")){
$php_data_array = Array(); // create PHP array
while ($row = $stmt->fetch_row()) {
$php_data_array[] = $row; // Adding to array
}
}else{
echo $link->error;
}
echo json_encode($php_data_array);
On the echo json_encode($php_data_array);
, it gives the this current output: [["36","154"],["37","247"],["38","275"]]
. So the first string in the array (36, 37, 38) is the week number, and the second one the number of rows where color is RED. Now, I also want to add where color is BLUE in the same array, so the expected value should be something like: [["36","154","166"],["37","247","265"],["38","275","298"]]
.
What approach should I use to do this?
Just add another column:
SELECT WEEK(date) as week, SUM(color = 'RED') as red, SUM(color = 'BLUE') as blue
FROM sales
WHERE color IN ('RED', 'BLUE') AND YEAR(date) = YEAR(NOW())
GROUP BY WEEK(date)
ORDER BY WEEK(date) ASC;
Note the changes to the query:
SUM()
does conditional aggregation for each color. ORDER BY
is by the column being aggregated. Use conditional aggregation:
select week(date) week_date, sum(color = 'RED') cnt_red, sum(color = 'BLUE') cnt_blue
from sales
where color in ('RED', 'BLUE') and date >= date_format(current_date, '%Y-%m-01')
group by week(date)
order by week_date
Note that this uses direct filtering on the date
column, without applying functions on the filtered column. This is more efficient that year(date) = year(now())
, especially if you have an index on that column.
I also changed the order by
clause: obviously, you want to order by week rather than month (in most databases, that's a compilation error, because the month does not belong to the group by
clause).
You can use dynamic query as another option :
SET @sql = NULL;
SELECT GROUP_CONCAT(
DISTINCT
CONCAT(
'SUM( color =''', color, ''' ) AS ',color
)
)
INTO @sql
FROM sales s;
SET @sql = CONCAT('SELECT WEEK(date) AS WEEK,',@sql,
' FROM sales
WHERE YEAR(date) = YEAR(NOW())
GROUP BY WEEK
ORDER BY WEEK');
and then call from php code block such as :
if($stmt = $link->query( @sql )){ ....
$php_data_array = Array(); // create PHP array
....
This way, no need to add each color name to be grouped individually, the query pivots all color column values whichever exist within the table. New colors might be added or existing ones might be deleted without constructing new querie.
Demo (in order to show result of the query)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.