简体   繁体   中英

SQL Query count rows where multiple column-values

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:

  • The SUM() does conditional aggregation for each color.
  • The columns are given names, which can be used to reference them in the application.
  • The 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM