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

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']

Related

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

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>

One query to fetch from A, join field values from B as row fields in A and then filter and sort?

I have created the following tables in my database for the purpose of creating an easy-to-reuse-and-configure CMS. I can create a PHP array of objects with any number of any named properties and with this structure it can be saved without having to make tables for every object type. A bit like Wordpress uses the 'posts' table for every custom item type.
struct (id, type)
1, 'article'
2, 'article'
3, 'employee'
4, 'article'
...
struct_fields (id, struct_id, sub_id, type, val)
1, 1, 'title', 'string', 'Great article'
2, 1, 'publish_date', 'datetime', '2019-03-02 21:00:00'
3, 1, 'active', 'boolean', 1
4, 1, 'body', 'wysiwyg', '<p>Contents</p>'
5, 2, 'title', 'string', 'Another fantastic article'
6, 2, 'publish_date', 'datetime', '2018-03-01 14:32:17'
7, 2, 'active', 'boolean', 1
8, 2, 'body', 'wysiwyg', '<p>Cool contents</p>'
9, 3, 'firstname', 'string', 'Jos'
10, 3, 'lastname', 'string', 'Fabre'
11, 4, 'title', 'string', 'This is amazing'
12, 4, 'publish_date', 'datetime', '2018-03-01 19:21:34'
13, 4, 'active', 'boolean', 0
14, 4, 'body', 'wysiwyg', '<p>Bad content!</p>'
...
I'm seriously struggling to create the one query that can take out a list of structs with their related fields as properties.
I'm not sure it's even possible.
I would like to sort on properties (thus fields in the related table) as well
e.g. I would like to create a query that can grab the latest 3 active articles of which publish_date is in the past.
I've struggled with JOIN and GROUP BY for days now.
The query for a different type of struct could be ordered by a specific field, or filtered on another field, or both..
So, e.g. for articles I would like the output to be this:
[id, active, publish_date, title, body]
And then filter on active and sort on publish_date. The id would come from the struct table, the rest of the fields from the joined fields in the struct_fields table.
And for employees it should be this:
[id, firstname, lastname]
And then sorted on lastname ASC, firstname ASC
In one case I was able to get the struct_field properties into the result row fields with MAX, but I could not sort on them without sql errors
SELECT struct.id, struct.type, struct.published,
MAX(CASE WHEN struct_fields.sub_id = 'active' THEN struct_fields.vc1 ELSE NULL END) AS active,
MAX(CASE WHEN struct_fields.sub_id = 'title' THEN struct_fields.vc1 ELSE NULL END) AS title,
MAX(CASE WHEN struct_fields.sub_id = 'body' THEN struct_fields.tx1 ELSE NULL END) AS body,
MAX(CASE WHEN struct_fields.sub_id = 'allday' THEN struct_fields.vc1 ELSE NULL END) AS allday,
MAX(CASE WHEN struct_fields.sub_id = 'start_datetime' THEN struct_fields.vc1 ELSE NULL END) AS start_datetime,
MAX(CASE WHEN struct_fields.sub_id = 'end_datetime' THEN struct_fields.vc1 ELSE NULL END) AS end_datetime
FROM struct
INNER JOIN struct_fields ON (struct_fields.struct_id = struct.id)
WHERE struct.type = 'events'
GROUP BY struct.id
Help! Can this even be done in one query??
UPDATE: #Nic3500 suggested posting create sql and some sample inserts, so here they are: https://pastebin.com/raw/0hPYByDq
This could happen if you use alias name for order by
but you could use also the column position eg:
SELECT struct.id, struct.type, struct.published,
MAX(CASE WHEN struct_fields.sub_id = 'active' THEN struct_fields.vc1 ELSE NULL END) AS active,
MAX(CASE WHEN struct_fields.sub_id = 'title' THEN struct_fields.vc1 ELSE NULL END) AS title,
MAX(CASE WHEN struct_fields.sub_id = 'body' THEN struct_fields.tx1 ELSE NULL END) AS body,
MAX(CASE WHEN struct_fields.sub_id = 'allday' THEN struct_fields.vc1 ELSE NULL END) AS allday,
MAX(CASE WHEN struct_fields.sub_id = 'start_datetime' THEN struct_fields.vc1 ELSE NULL END) AS start_datetime,
MAX(CASE WHEN struct_fields.sub_id = 'end_datetime' THEN struct_fields.vc1 ELSE NULL END) AS end_datetime
FROM struct
INNER JOIN struct_fields ON (struct_fields.struct_id = struct.id)
WHERE struct.type = 'events'
GROUP BY struct.id
order 1,2,3
in this way you should be a bit more indendent and you could build a dynamic range or set for you order by
I think -probably due to actively diving into this again after getting your answers- I managed to come up with a solution in this query (in the case of struct type = articles)
SELECT struct.id, struct.type, struct.published,
MAX(CASE WHEN struct_fields.sub_id = 'active' THEN struct_fields.vc1 ELSE NULL END) AS active,
MAX(CASE WHEN struct_fields.sub_id = 'title' THEN struct_fields.vc1 ELSE NULL END) AS title,
MAX(CASE WHEN struct_fields.sub_id = 'body' THEN struct_fields.tx1 ELSE NULL END) AS body,
MAX(CASE WHEN struct_fields.sub_id = 'publish_date' THEN struct_fields.vc1 ELSE NULL END) AS publish_date
FROM struct
INNER JOIN struct_fields ON (struct_fields.struct_id = struct.id)
WHERE struct.type = 'articles'
GROUP BY struct.id
HAVING (active = 1 AND CAST(publish_date as datetime)<NOW() )
ORDER BY publish_date DESC
LIMIT 7

MYSQL SELECT value AS YEAR(CURDATE)

I am trying to get data from table, as shown on the code. Instead of ThisYear and LastYear; I want to display Year number depending on current year. I want to try use something like "Year(curdate())" and "Year(curdate()) - 1"; and column headers will be 2017 and 2016 instead of ThisYear and LastYear.
SELECT Months AS Months,
SUM(if(Years = Year(curdate()) AS ThisYear,
SUM(if(Years = Year(curdate())-1, in_amount, null)) AS LastYear,
FIELD(Months, 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December') AS `FIELD(Months, 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')` FROM ao_vw_revenue GROUP BY Months ORDER BY FIELD(Months, 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December')
Any help? Thanks.

sum doesn't work while I use left join and group by

I have two table: imports and orders: I have attached these respectively.
I want the followings:
1. sum amount of same product_id in imports table
2. sum of pieces of same product_id in orders table as status wise.
my query is:
SELECT `Import`.*,
SUM( case when orders.status = "sold" THEN orders.pieces else 0 end) as total_sell,
SUM( case when orders.status = "No contact" THEN orders.pieces else 0 end) as no_contact,
SUM( case when orders.status = "confirmed" THEN orders.pieces else 0 end) as confirmed,
SUM( case when orders.status = "canceled" THEN orders.pieces else 0 end) as canceled
FROM `amrajegeachi`.`imports` AS `Import`
LEFT JOIN `orders`
ON `Import`.`product_id` = `orders`.`product_id`
WHERE 1 = 1
GROUP BY `Import`.`id`
and result for this query:
Array
(
[0] => Array
(
[Import] => Array
(
[id] => 1
[category_id] => 2
[product_id] => 2
[amount] => 50
[cost] => 8320
[comment] => transportation and others cost: 100
[created] => 2015-06-23 19:21:10
)
[0] => Array
(
[total_sell] => 10
[no_contact] => 1
[confirmed] => 2
[canceled] => 0
)
)
[1] => Array
(
[Import] => Array
(
[id] => 2
[category_id] => 2
[product_id] => 2
[amount] => 15
[cost] => 3000
[comment] =>
[created] => 2015-06-22 18:10:36
)
[0] => Array
(
[total_sell] => 10
[no_contact] => 1
[confirmed] => 2
[canceled] => 0
)
)
[2] => Array
(
[Import] => Array
(
[id] => 3
[category_id] => 2
[product_id] => 1
[amount] => 15
[cost] => 2000
[comment] =>
[created] => 2015-06-23 19:20:15
)
[0] => Array
(
[total_sell] => 10
[no_contact] => 0
[confirmed] => 0
[canceled] => 0
)
)
)
My expected result is:
Array
(
[0] => Array
(
[Import] => Array
(
[id] => 1
[category_id] => 2
[product_id] => 2
[amount] => 65
[cost] => 8320
[comment] => transportation and others cost: 100
[created] => 2015-06-23 19:21:10
)
[0] => Array
(
[total_sell] => 10
[no_contact] => 1
[confirmed] => 2
[canceled] => 0
)
)
[2] => Array
(
[Import] => Array
(
[id] => 3
[category_id] => 2
[product_id] => 1
[amount] => 15
[cost] => 2000
[comment] =>
[created] => 2015-06-23 19:20:15
)
[0] => Array
(
[total_sell] => 10
[no_contact] => 0
[confirmed] => 0
[canceled] => 0
)
)
)
How can I do this? I tried in different way such as:
SELECT `Import`.*, SUM(`Import`.`amount`) as total_import,
SUM( case when orders.status = "sold" THEN orders.pieces else 0 end) as total_sell,
SUM( case when orders.status = "No contact" THEN orders.pieces else 0 end) as no_contact,
SUM( case when orders.status = "confirmed" THEN orders.pieces else 0 end) as confirmed,
SUM( case when orders.status = "canceled" THEN orders.pieces else 0 end) as canceled
FROM `amrajegeachi`.`imports` AS `Import`
LEFT JOIN `orders`
ON `Import`.`product_id` = `orders`.`product_id`
WHERE 1 = 1
GROUP BY `Import`.`id`
But no luck :'(
I am guessing that you want information about each product. If so, you can do this in a few ways. Here is a union all method:
SELECT product_id, sum(amount) as total_import,
sum( case when status = 'sold' THEN pieces else 0 end) as total_sell,
sum( case when status = 'No contact' THEN pieces else 0 end) as no_contact,
sum( case when status = 'confirmed' THEN pieces else 0 end) as confirmed,
sum( case when status = 'canceled' THEN pieces else 0 end) as canceled
from ((select i.product_id, amount, NULL as status, NULL as pieces
from `amrajegeachi`.`imports` i
) union all
(select o.product_id, NULL, o.status, o.pieces
from `orders` o
)
) io
group by product_id;
SELECT `Import`.*, SUM(`Import`.`amount`) as total_import,
SUM( case when orders.status = "sold" THEN orders.pieces else 0 end) as total_sell,
SUM( case when orders.status = "No contact" THEN orders.pieces else 0 end) as no_contact,
SUM( case when orders.status = "confirmed" THEN orders.pieces else 0 end) as confirmed,
SUM( case when orders.status = "canceled" THEN orders.pieces else 0 end) as canceled
FROM `amrajegeachi`.`imports` AS `Import`
LEFT JOIN `orders`
ON `Import`.`product_id` = `orders`.`product_id`
WHERE 1 = 1
GROUP BY `Import`.`id

Generating a list of years/months in MySQL

Currently for my blog I get a list of years/dates using the following code:
$monthList = array(
1 => 'January',
2 => 'February',
3 => 'March',
4 => 'April',
5 => 'May',
6 => 'June',
7 => 'July',
8 => 'August',
9 => 'September',
10 => 'November',
11 => 'October',
12 => 'December'
);
$nav = array();
for ($year = 2009; $year <= date('Y'); $year++) {
foreach ($monthList as $id => $month) {
$this->tru->query->runRaw(array(
'name' => 'get-headline-count',
'sql' => 'SELECT
COUNT(id) as count
FROM
wp_'.$this->getId().'_posts
WHERE
post_status = \'publish\' AND
post_type = \'post\' AND
post_parent = \'0\' AND
YEAR(post_date) = '.$year.' AND
MONTH(post_date) = '.$id.'',
'connection' => 'article'
));
$temp = $this->tru->query->getArray('get-headline-count');
if ($temp['count'] > 0) {
$nav[$year][$id] = $temp['count'];
}
}
}
krsort($nav);
return array(
'month' => $monthList,
'nav' => $nav
);
This was all great at first, but now that I've got a few years worth of data and a few months this isn't going to cut it anymore. I've never done anything like this before, I usually deal with timestamps.
You can replace the loop with this one query
SELECT
YEAR(post_date) as yr, MONTH(post_date) as mn, COUNT(id) as count
FROM
wp_posts
WHERE
post_status = 'publish' AND
post_type = 'post' AND
post_parent = '0'
GROUP BY YEAR(post_date), MONTH(post_date)