Please try the following...
SELECT CONCAT( 'SELECT department.id AS `Department No`,
department.departmentName AS `Department Name`',
GROUP_CONCAT( ', SUM( date_',
DATE_FORMAT( salesDate, '%d_%M' ),
'.sales ) AS `',
DATE_FORMAT( salesDate, '%e-%M' ),
'`',
SEPARATOR '' ),
' FROM department',
GROUP_CONCAT( ' LEFT JOIN departmentSales AS date_',
DATE_FORMAT( salesDate, '%d_%M' ),
' ON department.id = date_',
DATE_FORMAT( salesDate, '%d_%M' ),
'.department_id AND date_',
DATE_FORMAT( salesDate, '%d_%M' ),
'.salesDate = `',
DATE_FORMAT( salesDate, '%Y-%M-%d' ),
'`',
SEPARATOR '' ),
' GROUP BY department.id
ORDER BY department.id
UNION
SELECT `Totals`,
` `,
GROUP_CONCAT( ', SUM( date_',
DATE_FORMAT( salesDate, '%d_%M' ),
'.sales )',
SEPARATOR '' ),
' FROM department',
GROUP_CONCAT( ' LEFT JOIN departmentSales AS date_',
DATE_FORMAT( salesDate, '%d_%M' ),
' ON department.id = date_',
DATE_FORMAT( salesDate, '%d_%M' ),
'.department_id AND date_',
DATE_FORMAT( salesDate, '%d_%M' ),
'.salesDate = `',
DATE_FORMAT( salesDate, '%Y-%M-%d' ),
'`',
SEPARATOR '' ),
' ) INTO @salesQuery
FROM ( SELECT DISTINCT salesDate
FROM departmentSales
WHERE salesDate BETWEEN FROM_DAYS( TO_DAYS( targetDate ) -
DAYOFMONTH( targetDate ) +
1
)
AND LAST_DAY( targetDate )
) AS salesDateFinder;
PREPARE salesTotals FROM @salesQuery;
EXECUTE salesTotals;
This attempt is based on code found at mysql select dynamic row values as column names, another column as value. I am concerned about the group_concat_max_len variable being a problem. If it is then I'll step up my research into the CASE method eggyal mentioned. If it is not a problem, then I'll take things a bit easier.
Most of the lines here actually form just one SQL statement. It takes the list of salesDate
values constructed by the subquery near the end, which are then used to help construct a rather long string containing the SQL statement to be run against the database.
The string is formed from a list of substrings specified as the arguments to the function CONCAT()
, which you can read about at https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_concat.
The string starts by specifying that the fields id
and departmentName
from the table department
should be the first selected for each record, followed by the SUM()
of each date's sales for that department. Each date field is given a name like date_09_March
and in the output a heading like 9-March
.
The repeated segments of the string are achieved by using the GROUP_CONCAT
function, which you can read about at https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_group-concat.
After the fields are specified the string specifies that the values should come from a temporary table formed from department
LEFT JOIN
ed with an instance of the departmentSales
table for each date, with each instance being given an alias like date_09_March
and joined on its department_id
field to the id
field of department
.
Once it is formed, the temporary table's records are grouped by department.id
so that the totals for each department may be calculated. The output is then sorted by department.id
.
The statement used to produce this sorted output and its column headings is then joined to another (somewhat simpler) statement used to generate the totals row. The string containing the SQL statement formed by the concatenation of each substring is then assigned to the variable @salesQuery, prepared and executed.
If you have any questions or comments, then please feel free to post a Comment accordingly.
Further Reading
https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html (for information on the DATE
functions used)