Bars are showing up even when value is zero - Google Charts - mysql

I have created a monthly chart using Google charts but the bars are showing up even when the value is zero.
Here is the screenshot of it
and here is the code and I know code is vulnerable to SQL Injection. You can ignore it. This is only for testing purpose
Previously order_total_amount column was set to "VARCHAR" datatype, then someone suggested that it should set to the "INT". So I changed it from Varchar to Int. But that didn't solved the problem. Bar is still showing up despite having 0 value
<script type="text/javascript">
google.charts.load('current', {'packages':['bar']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Monthly', 'Sales'],
<?php
$sale_chart = "SELECT
SUM(IF(month = 'Jan', total, 0)) AS 'Jan',
SUM(IF(month = 'Feb', total, 0)) AS 'Feb',
SUM(IF(month = 'Mar', total, 0)) AS 'Mar',
SUM(IF(month = 'Apr', total, 0)) AS 'Apr',
SUM(IF(month = 'May', total, 0)) AS 'May',
SUM(IF(month = 'Jun', total, 0)) AS 'Jun',
SUM(IF(month = 'Jul', total, 0)) AS 'Jul',
SUM(IF(month = 'Aug', total, 0)) AS 'Aug',
SUM(IF(month = 'Sep', total, 0)) AS 'Sep',
SUM(IF(month = 'Oct', total, 0)) AS 'Oct',
SUM(IF(month = 'Nov', total, 0)) AS 'Nov',
SUM(IF(month = 'Dec', total, 0)) AS 'Dec'
FROM
(SELECT
MIN(DATE_FORMAT(order_date, '%b')) AS month,
SUM(order_total_amount) AS total
FROM
invoice_order
WHERE
user_id = '$user_id'
GROUP BY YEAR(order_date) , MONTH(order_date)
ORDER BY YEAR(order_date) , MONTH(order_date)) AS sale";
$sale_chart_query = mysqli_query($connection,$sale_chart) or die(mysqli_error($connection));
$sale_chart_array = mysqli_fetch_assoc($sale_chart_query);
foreach($sale_chart_array as $x => $val) { ?>
['<?php echo $x; ?>','<?php echo $val; ?>'],
<?php } ?>
]);
var options = {
};
var chart = new google.charts.Bar(document.getElementById('chart_div'));
chart.draw(data, google.charts.Bar.convertOptions(options));
}
</script>
After replacing zero with null, that is how it showing up the result

using a value of null in the chart's data table will prevent a bar from appearing.
see following working snippet...
in this case, you're including strings instead of numbers in the data table.
remove the single quotes from the second array value, here...
['<?php echo $x; ?>',<?php echo $val; ?>],
google.charts.load('current', {
packages: ['bar']
}).then(function drawChart() {
var data = google.visualization.arrayToDataTable([
['Monthly', 'Sales'],
['Jan', 1000],
['Feb', null],
['Mar', null],
['Apr', null],
['May', 40000],
['Jun', null],
['Jul', null],
['Aug', null],
['Sep', null],
['Oct', null],
['Nov', null],
['Dec', null]
]);
var options = {};
var chart = new google.charts.Bar(document.getElementById('chart_div'));
chart.draw(data, google.charts.Bar.convertOptions(options));
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>

Related

How to get max value of multiple column in a single row?

trying to get max value of months column in a single row
for example i want to get max value from jan~ dec from first column which is currently 5 is the max value
preferably do it in laravel
See the PHP max function
To get the month name(s) (remember more than one month could have the maximum value), you'll need to implement a loop.
$max_day = max(
$record->jan,
$record->feb,
$record->mar,
$record->apr,
$record->may,
$record->jun,
$record->jul,
$record->aug,
$record->sep,
$record->oct,
$record->nov,
$record->dec
);
$columns = [
'jan' => 'January',
'feb' => 'February',
'mar' => 'March',
'apr' => 'April',
'may' => 'May',
'jun' => 'June',
'jul' => 'July',
'aug' => 'August',
'sep' => 'September',
'oct' => 'October',
'nov' => 'November',
'dec' => 'December',
];
$max_months = [];
foreach ($columns as $column_name => $month_name) {
if ($record->{$column_name} === $max_day) {
$max_months[] = $month_name;
}
}
// $max_months e.g. ['January', 'February']

What would cause a mysql query based on month() and year() to be faster than querying against its numeric equivalent directly?

I am attempting to speed up a SQL query in MySql 5.7 by replacing YEAR() and MONTH() functions with their numeric equivalents during insert time. Specifically, I added the columns reportMonth, reportYear, both bigint(20) for that.
Interestingly, that approach is much slower. Why is that so? Shouldn't it be faster to run a query with fewer functions in it?
This takes about 12 seconds to complete. (with YEAR() and MONTH() functions)
SELECT
ProductTitle AS 'ProductTitle',
YEAR(ReportPeriodEndDay) AS 'Year',
SUM(CASE WHEN MONTH(ReportPeriodEndDay) = 1 THEN OrderedRevenue END) AS 'Jan',
SUM(CASE WHEN MONTH(ReportPeriodEndDay) = 2 THEN OrderedRevenue END) AS 'Feb',
SUM(CASE WHEN MONTH(ReportPeriodEndDay) = 3 THEN OrderedRevenue END) AS 'Mar',
SUM(CASE WHEN MONTH(ReportPeriodEndDay) = 4 THEN OrderedRevenue END) AS 'Apr',
SUM(CASE WHEN MONTH(ReportPeriodEndDay) = 5 THEN OrderedRevenue END) AS 'May',
SUM(CASE WHEN MONTH(ReportPeriodEndDay) = 6 THEN OrderedRevenue END) AS 'Jun',
SUM(CASE WHEN MONTH(ReportPeriodEndDay) = 7 THEN OrderedRevenue END) AS 'Jul',
SUM(CASE WHEN MONTH(ReportPeriodEndDay) = 8 THEN OrderedRevenue END) AS 'Aug',
SUM(CASE WHEN MONTH(ReportPeriodEndDay) = 9 THEN OrderedRevenue END) AS 'Sep',
SUM(CASE WHEN MONTH(ReportPeriodEndDay) = 10 THEN OrderedRevenue END) AS 'Oct',
SUM(CASE WHEN MONTH(ReportPeriodEndDay) = 11 THEN OrderedRevenue END) AS 'Nov',
SUM(CASE WHEN MONTH(ReportPeriodEndDay) = 12 THEN OrderedRevenue END) AS 'Dec',
SUM(OrderedRevenue) AS 'TOTAL'
FROM
`sales_diagnostic_summary_orderedrevenuelevel`
GROUP BY ProductTitle, Year
WITH ROLLUP;
Result from EXPLAIN
# id, select_type, table, partitions, type, possible_keys, key, key_len, ref, rows, filtered, Extra
1, SIMPLE, sales_diagnostic_summary_orderedrevenuelevel, , ALL, , , , , 745140, 100.00, Using temporary; Using filesort
This takes more than 120 seconds (with numeric equivalents)
SELECT
ProductTitle AS 'ProductTitle',
reportYear AS 'Year',
SUM(CASE WHEN reportMonth = 1 THEN OrderedRevenue END) AS 'Jan',
SUM(CASE WHEN reportMonth = 2 THEN OrderedRevenue END) AS 'Feb',
SUM(CASE WHEN reportMonth = 3 THEN OrderedRevenue END) AS 'Mar',
SUM(CASE WHEN reportMonth = 4 THEN OrderedRevenue END) AS 'Apr',
SUM(CASE WHEN reportMonth = 5 THEN OrderedRevenue END) AS 'May',
SUM(CASE WHEN reportMonth = 6 THEN OrderedRevenue END) AS 'Jun',
SUM(CASE WHEN reportMonth = 7 THEN OrderedRevenue END) AS 'Jul',
SUM(CASE WHEN reportMonth = 8 THEN OrderedRevenue END) AS 'Aug',
SUM(CASE WHEN reportMonth = 9 THEN OrderedRevenue END) AS 'Sep',
SUM(CASE WHEN reportMonth = 10 THEN OrderedRevenue END) AS 'Oct',
SUM(CASE WHEN reportMonth = 11 THEN OrderedRevenue END) AS 'Nov',
SUM(CASE WHEN reportMonth = 12 THEN OrderedRevenue END) AS 'Dec',
SUM(OrderedRevenue) AS 'TOTAL'
FROM
`sales_diagnostic_summary_orderedrevenuelevel`
GROUP BY ProductTitle, Year
WITH ROLLUP;
Result from EXPLAIN
# id, select_type, table, partitions, type, possible_keys, key, key_len, ref, rows, filtered, Extra
1, SIMPLE, sales_diagnostic_summary_orderedrevenuelevel, , ALL, , , , , 745140, 100.00, Using filesort
Table mapping via DESCRIBE
# Field, Type, Null, Key, Default, Extra
ASIN, text, YES, MUL, ,
ProductTitle, text, YES, , ,
OrderedRevenue, double, YES, , ,
OrderedRevenuePercentOfTotal, double, YES, , ,
OrderedRevenuePriorPeriod, double, YES, , ,
OrderedRevenueLastYear, double, YES, , ,
OrderedUnits, double, YES, , ,
OrderedUnitsPercentOfTotal, double, YES, , ,
OrderedUnitsPriorPeriod, double, YES, , ,
OrderedUnitsLastYear, double, YES, , ,
SubcategorySalesRank, bigint(20), YES, , ,
SubcategoryBetterWorse, double, YES, , ,
AverageSalesPrice, double, YES, , ,
AverageSalesPricePriorPeriod, double, YES, , ,
ChangeInGVPriorPeriod, double, YES, , ,
ChangeInGVLastYear, double, YES, , ,
RepOOS, double, YES, , ,
RepOOSPercentOfTotal, double, YES, , ,
RepOOSPriorPeriod, double, YES, , ,
LBBPrice, double, YES, , ,
ReportPeriodStartDay, datetime, YES, , ,
ReportPeriodEndDay, datetime, YES, , ,
ReportDownloadDate, datetime, YES, , ,
ReportPeriod, text, YES, , ,
ReportFilename, text, YES, , ,
marketplace, text, YES, , ,
vendorId, text, YES, , ,
reportYear, bigint(20), YES, MUL, ,
reportMonth, bigint(20), YES, MUL, ,
reportWeek, bigint(20), YES, , ,
reportQuarter, bigint(20), YES, , ,
reportDayOfWeek, bigint(20), YES, , ,
reportDayOfYear, bigint(20), YES, , ,
There seems to be some optimization linked to the YEAR function, of which DESCRIBE knows nothing about (which is logical enough).
The way I would have implemented it is, when the YEAR function is called, if it sees that MONTH is called too, it does additional binning for the month value. Then, that part of the work is already done, and better, than through a CASE on an unrelated field (because the fact that it is called reportMonth does not make it related).
Since each year has no more than 12 months, that seems a worthwhile optimization - it won't use too much memory and the potential rewards are appreciable.
If you have a lot of sales per product, you might try a straight grouping by reportYear and reportMonth, and then run the CASE pivoting as a wrapping SELECT. Something like:
SELECT
ProductTitle,
reportYear as `Year`,
SUM(IF (reportMonth = 1, OrderedRevenue, 0) AS 'Jan',
...
SUM(IF (reportMonth = 12, OrderedRevenue, 0) AS 'Dec',
SUM(OrderedRevenue) AS 'TOTAL'
FROM (
SELECT productTitle,
reportYear,
reportMonth,
SUM(OrderedRevenue) AS OrderedRevenue
FROM
`sales_diagnostic_summary_orderedrevenuelevel`
GROUP BY ProductTitle, reportYear, reportMonth
) AS firstGrouping;
Very likely, having an index
CREATE INDEX myIndex ON
sales_diagnostic_summary_orderedrevenuelevel(ProductTitle,
reportYear, reportMonth, OrderedRevenue);
while costing something during UPDATE/DELETE/INSERTs, should improve things during this kind of SELECT. You might want to try the DATE version of both double-select and indexing on for size.
Additionally, I don't think there's any reason to store year, month and week as BIGINT. It won't make all that difference either in performance or in storage, but it still smells a bit to me.

Selecting columns for display based on user criterion in MSAccess

I have an access table with columns
Account Id, account description, GL Code, year, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec. The months columns holds the amount.
I want if user selects Jan on Form than Account Id, account description, Gl code,year and Jan gets displayed. Similarly if user selects Feb than Account Id account description, gl code, year and Feb gets displayed. Similarly for other months.
Have no idea on how to do this. To my knowledge we can filter rows but not the columns.
Please suggest if any possible solution. Please note that I cannot change the database design as the data is getting downloaded from ERP package.
Create a query where you set the SQL dynamically:
Dim qd As DAO.QueryDef
Dim SQL As String
Dim MonthName As String
MonthName = "Feb" ' Month to search.
Set qd = CurrentDb.QueryDefs("YourQuery")
SQL = "Select [GL Code], [year], [" & MonthName & "] As Amount From YourTable"
qd.SQL = SQL
Now, open the query or open a recordset using the query as source.
SQL only:
Select
[GL Code],
[year],
IIf(MonthName = 'Jan', [Jan],
IIf(MonthName = 'Feb', [Feb],
IIf(MonthName = 'Mar', [Mar],
IIf(MonthName = 'Apr', [Apr],
IIf(MonthName = 'May', [May],
IIf(MonthName = 'Jun', [Jun],
IIf(MonthName = 'Jul', [Jul],
IIf(MonthName = 'Aug', [Aug],
IIf(MonthName = 'Sep', [Sep],
IIf(MonthName = 'Oct', [Oct],
IIf(MonthName = 'Nov', [Nov],
IIf(MonthName = 'Dec', [Dec])))))))))))) As Amount
From
YourTable

Mysql query to get count per months and year using entry date and outing date

i have a table collaborator that contains:
the columns : hiring_date and release_date ( date type)
i would like to calculate the total number of collaborators per month of a year
using hiring_date and release_date
I guess you are asking for something like this but please, try to give more information when asking
SELECT COUNT(*) FROM collaborator WHERE hiring_date >= date AND release_date<= date
You can use "GROUP BY" for this.
e.g., To calculate the total number of collaborators per month using hiring_date :
SELECT MONTH(hiring_date),COUNT(*) FROM `collaborator`
GROUP BY MONTH(hiring_date);
To calculate the total number of collaborators per month of a year using release_date, use :
SELECT MONTH(release_date),COUNT(*) FROM `collaborator `
GROUP BY MONTH(release_date)
WHERE YEAR(release_date) = <year>;
this code is to get number of hiring collaborators on 2016 per month
SELECT
SUM(IF(month = '1', total, 0)) AS 'Jan',
SUM(IF(month = '2', total, 0)) AS 'Feb',
SUM(IF(month = '3', total, 0)) AS 'Mar',
SUM(IF(month = '4', total, 0)) AS 'Apr',
SUM(IF(month = '5', total, 0)) AS 'May',
SUM(IF(month = '6', total, 0)) AS 'Jun',
SUM(IF(month = '7', total, 0)) AS 'Jul',
SUM(IF(month = '8', total, 0)) AS 'Aug',
SUM(IF(month = '9', total, 0)) AS 'Sep',
SUM(IF(month = '10', total, 0)) AS 'Oct',
SUM(IF(month = '11', total, 0)) AS 'Nov',
SUM(IF(month = '12', total, 0)) AS 'Dec'
FROM (
SELECT month(DATE_ENTREE) AS month , count(DATE_ENTREE) as total
FROM collaborateur where YEAR(DATE_ENTREE) =2016
GROUP BY month(DATE_ENTREE)) as e
and this code is the number of release per month on 2016
SELECT
SUM(IF(month = '1', total, 0)) AS 'Jan',
SUM(IF(month = '2', total, 0)) AS 'Feb',
SUM(IF(month = '3', total, 0)) AS 'Mar',
SUM(IF(month = '4', total, 0)) AS 'Apr',
SUM(IF(month = '5', total, 0)) AS 'May',
SUM(IF(month = '6', total, 0)) AS 'Jun',
SUM(IF(month = '7', total, 0)) AS 'Jul',
SUM(IF(month = '8', total, 0)) AS 'Aug',
SUM(IF(month = '9', total, 0)) AS 'Sep',
SUM(IF(month = '10', total, 0)) AS 'Oct',
SUM(IF(month = '11', total, 0)) AS 'Nov',
SUM(IF(month = '12', total, 0)) AS 'Dec'
FROM (
SELECT month(DATEE_SORTIE_COLLABORATEUR) AS month , count(DATEE_SORTIE_COLLABORATEUR) as total
FROM collaborateur where YEAR(DATEE_SORTIE_COLLABORATEUR) =2016
GROUP BY month(DATEE_SORTIE_COLLABORATEUR)) as s
my objective is to calculate total number of collaborator per month
hope this can help you to understand what i mean

Convert crosstab query into a view

I have the following query which I want to convert to a view:
SELECT
PartNum,
SUM(IF(DAYOFWEEK(DeliveryDate) = '2', value, NULL)) AS 'Mon',
SUM(IF(DAYOFWEEK(DeliveryDate) = '3', value, NULL)) AS 'Tue',
SUM(IF(DAYOFWEEK(DeliveryDate) = '4', value, NULL)) AS 'Wed',
SUM(IF(DAYOFWEEK(DeliveryDate) = '5', value, NULL)) AS 'Thu',
SUM(IF(DAYOFWEEK(DeliveryDate) = '6', value, NULL)) AS 'Fri',
SUM(IF(DAYOFWEEK(DeliveryDate) = '7', value, NULL)) AS 'Sat',
SUM(IF(DAYOFWEEK(DeliveryDate) = '1', value, NULL)) AS 'Sun',
SUM(IF(DeliveryDate > DATE_ADD(CURDATE(),INTERVAL 7 DAY), value, NULL)) AS 'Future'
FROM (
SELECT PartNum, DeliveryDate , SUM(Ordered) value FROM v_archived_items_due
GROUP BY PartNum, DeliveryDate
) t
GROUP BY PartNum;
When I try to save it as a view, I get the following error:
1349 - Views SELECT contains a subquery in the FROM clause.
The query works fine by itself. How do I turn it into a view?
MySQL does not allow subqueries in view so, without seeing any sample data to see how to rework this without the subqyery. Since this is working as expected, I would create a view of your subquery:
create view view1 as
SELECT PartNum, DeliveryDate , SUM(Ordered) value
FROM v_archived_items_due
GROUP BY PartNum, DeliveryDate;
Then just call this view in your query:
SELECT
PartNum,
SUM(IF(DAYOFWEEK(DeliveryDate) = '2', value, NULL)) AS 'Mon',
SUM(IF(DAYOFWEEK(DeliveryDate) = '3', value, NULL)) AS 'Tue',
SUM(IF(DAYOFWEEK(DeliveryDate) = '4', value, NULL)) AS 'Wed',
SUM(IF(DAYOFWEEK(DeliveryDate) = '5', value, NULL)) AS 'Thu',
SUM(IF(DAYOFWEEK(DeliveryDate) = '6', value, NULL)) AS 'Fri',
SUM(IF(DAYOFWEEK(DeliveryDate) = '7', value, NULL)) AS 'Sat',
SUM(IF(DAYOFWEEK(DeliveryDate) = '1', value, NULL)) AS 'Sun',
SUM(IF(DeliveryDate > DATE_ADD(CURDATE(),INTERVAL 7 DAY), value, NULL)) AS 'Future'
FROM view1
GROUP BY PartNum;
Behavoiur as designed
http://dev.mysql.com/doc/refman/5.1/en/create-view.html
You have to build a view from your subquery and use this.