I have following table
id item_id rating
1 10 1
2 10 2
3 10 2
4 10 3
5 10 3
6 10 3
7 10 4
How can I write a query so that I can get result as follows:
$ratings = array(
1 => 1,
2 => 2,
3 => 3,
4 => 1,
5 => 0
);
I need to use this query to write a php function to calculate average ratings by this function:
$total = 0;
$count = 0;
foreach($ratings as $number=>$frequency) {
$total += $number * $frequency;
$count += $frequency;
}
return $total / $count;
The basic COUNTing of records on the table won't produce 5 because there is no value 5 on the rating. But generating subquery which contains values from 1-5 and joining them using LEFT JOIN will do your desired result.
SELECT a.rating, COUNT(b.rating) totalCount
FROM
(
SELECT 1 rating UNION SELECT 2 UNION
SELECT 3 UNION SELECT 4 UNION
SELECT 5
) a
LEFT JOIN tableName b
ON a.rating = b.rating
GROUP BY a.rating
SQLFiddle Demo
SELECT
rating,
COUNT(rating) as Count
FROM rating
GROUP BY rating
Related
I've the below mysql table where I want to update multiple rows of approval_status field with 1 if the quantity passed is more than the qty_req value using MySql or PHP.
Requisition table:
id
part_id
qty_req
approval_status
1
16
20
0
2
17
30
0
3
16
40
0
4
17
50
0
5
17
60
0
Example:
$update_status=Array (
[0] => Array ( [part_id] => 17 [qty] => 90 )
[1] => Array ( [part_id] => 16 [qty] => 70 )
)
From the above array, 90 is the quantity available for the part_id 17. I want to update the approval_status as 1 in the requisition table for the rows with the part_id as 17 with the below scenario:
Update the approval_status to 1 as the quantity of the first row with part_id 17 is 30 which is less than 90.
Update the approval_status to 1 as the quantity of the second row with part_id 17 is 30+50=80 which is less than 90.
Third row won't update as the total 30+50+60=140 is greater than 90.
Unfortunately, I couldn't find any tutorial to achieve this.
Any help would be appreciated. Thanks in advance.
Single data:
UPDATE test t1
NATURAL JOIN ( SELECT *, SUM(qty_req) OVER (ORDER BY reg_date) cum_sum
FROM test
WHERE part_id = #part_id ) t2
SET t1.approval_status = 1
WHERE cum_sum <= #qty;
Multiple data:
UPDATE test t1
NATURAL JOIN ( SELECT test.*,
SUM(qty_req) OVER (PARTITION BY part_id ORDER BY reg_date) cum_sum,
qty
FROM test
JOIN JSON_TABLE(#json,
'$[*]' COLUMNS ( part_id INT PATH '$.part_id',
qty INT PATH '$.qty')) jsontable USING (part_id) ) t2
SET t1.approval_status = 1
WHERE cum_sum <= qty;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=7cf062d81a138657dee78f3026623783
Column reg_date and unique index added for to provide definite and unambiguous rows ordering.
The solution applicable to MySQL 5.6:
UPDATE test t1
NATURAL JOIN ( SELECT t1.part_id,
t1.qty_req,
t1.approval_status,
t1.reg_date,
SUM(t2.qty_req) cum_sum
FROM test t1
JOIN test t2 USING (part_id)
WHERE t1.reg_date >= t2.reg_date
GROUP BY t1.part_id,
t1.qty_req,
t1.approval_status,
t1.reg_date ) t2
JOIN ( SELECT 17 part_id, 90 qty
UNION ALL
SELECT 16, 50 ) t3 USING (part_id)
SET t1.approval_status = 1
WHERE t2.cum_sum <= t3.qty
https://dbfiddle.uk/?rdbms=mysql_5.6&fiddle=0aad358941f66d1f385799072237d513
Source data must be formed as a query text - see subquery t3.
This is my table order:
+-------+-------+
| month | count |
+-------+-------+
| 6 | 11 |
| 11 | 27 |
| 12 | 9 |
+-------+-------+
I want to create a graph using fusioncharts. Let's say that the year is 2017. How do I put the missing month into the array of which fusioncharts I'm using? I'm stuck on the condition.
This is my code:
$strQuery2 = "SELECT DATE_FORMAT(order_date, '%c') as month, COUNT(*) AS cnt FROM orders where YEAR(order_date)='2017' GROUP BY month ORDER BY `month` DESC";
$result2 = $dbhandle->query($strQuery2);
// Push the data into the array
while($row2 = $result2->fetch_assoc()) {
$q = $row2["month"];
$w = $row2["cnt"];
$e = 0;
$x = 1;
if ($x != $q){
echo "true";
array_push($arrData2["data"],
array(
"label" => $row2[$x],
"value" => $row2[$e]
)
);
}
else{
echo "false";
array_push($arrData2["data"],
array(
"label" => $row2["month"],
"value" => $row2["cnt"]
)
);
}
$x++;
echo $row2["month"] . "<br />";
echo $row2["cnt"] . "<br />";
}
You never get a month from the database that isn't there. If you push data into an empty array:
array_push($arrData2["data"]
you still end up with an array that only contains the months returned from the database.
What you can do is first create an array with all 12 months:
$arrData2["data"]=range(1,12,false);
You have now an array that contains 12 elements (months) from 1 - 12, all with values of false. (You could use any value, an array or false if you need).
Now inside your resultloop, just replace the array elements you have values for:
$arrData2["data"][$row2["month"]] = array(
'label' => $row2["month"],
'value' => $row2["cnt"]
);
$arrData2 now will look like:
array(
1 => false,
2 => false,
3 => false,
4 => false,
5 => false,
6 => array('label'=> 6,'value'=> 11),
7 => false,
8 => false,
9 => false,
10 => false,
11 => array('label'=> 11,'value'=> 27),
12 => array('label'=> 12,'value'=> 9)
)
Now you can replace all the false values for arrays with value 0
So your whole code could be schortened to:
//set empty array
$arrData2['data'] = range(1, 12, false);
//fill elements we know
while($row2 = $result2->fetch_assoc()) {
$arrData2["data"][$row2["month"]] = array(
'label' => $row2["month"],
'value' => $row2["cnt"]
);
}
//replace the rest with 0
foreach($arrData2["data"] as $key => $value){
// skip what we already know
if($values !== false) continue;
// replace the rest
$arrData2["data"][$key]=array(
'label'=>$key,
'value'=> 0
);
}
echo print_r($arrData2,true);
There are basically two ways to approach it. One to fill missing months on PHP side and one on SQL. I will give you SQL version:
SELECT
m.`month`,
IFNULL(x.cnt, 0) AS cnt
FROM
(SELECT 1 AS `month` UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12) AS m
LEFT JOIN (SELECT DATE_FORMAT(order_date, '%c') as `month`, COUNT(*) AS cnt FROM orders where YEAR(order_date)='2017' GROUP BY `month`) AS x ON m.`month` = x.`month`
ORDER BY m.`month` DESC
It basically generates list of all months from 1 to 12 and if such month exists in your query than it is filled with real value. Otherwise it's zero.
Let's say I have the following table (keep in mind that this table will have 10000+ rows):
id total date
1 5 2015-05-16
2 8 2015-05-17
3 4 2015-05-18
4 9 2015-05-19
5 3 2015-05-20
I want the query to give the following result:
1
date => 2015-05-16
total => 5
2
date => 2015-05-17
total => 13
3
date => 2015-05-18
total => 17
4
date => 2015-05-19
total => 26
5
date => 2015-05-20
total -> 29
I can't think of any query that would do this right now, that's why I am not providing any code that I have tried.
Any thoughts? I am not sure if this is possible only with mysql, maybe I have to use and php.
This could be done using user defined variable in mysql and then get the running total as
select
id,
total,
date
date from
(
select
id,
#tot:= #tot+total as total,
date from my_table,(select #tot:=0)x
order by date
)x
You can do this -
SELECT
a.id,
a.date,
(SELECT SUM(b.total) FROM your_table WHERE b.date <= a.date) as new_total
FROM your_table a, your_table b
ORDER BY a.date ASC
This should do it:
select id, (select sum(total) from table a where a.date <= b.date) from table b
I have the folowing query that shows my products.
SELECT DISTINCT productsmap.id, attributes_product.waarde,
attributes_product.att_id, productsmap.name, productsmap.category
AS categoryId, brand.naam AS brand, productsmap.sku, categorie.name AS
category, productsmap.price, productsmap.shops
FROM productsmap
INNER JOIN categorie ON productsmap.category = categorie.id
INNER JOIN brand ON productsmap.brand = brand.id
INNER JOIN attributes_product ON productsmap.id = attributes_product.pmapid
WHERE productsmap.category
IN ( 2, 3, 4, 5, 6, 7, 8 )
AND productsmap.shops >0
AND (
productsmap.price >= 3.94
AND productsmap.price <= 204.99
)
AND productsmap.online =1
LIMIT 0 , 30
It gives the folowing results I cropped a bit:
(id) (waarde) (att_id) (name) (categoryId) (brand) (sku)
2 109 1 Name 4 Merk 70000
2 2013 2 Name etc etc etc
2 123 3 Name etc etc etc
3 103 1 Name2 etc etc
3 2012 2 Name2
3 123 3 Name2
4 110 1 3name
4 2013 2 3name
4 102 3 3name
Whit multiple times the same id and name only diffrent att_id and waarde. But i need to add to my query (attributes_product.att_id = 1 and waarde = 109) and (attributes_product.att_id = 2 and waarde = 2013)
But this is not possible because it are diffrent results. How can I solve this issue? Or on what can i search to solve this issue?
It attributes.product are att_id and waarde
TABLE PRODUCTS_CATEGORIES
product_id category_id link_type position
2 22 M 0
3 22 M 0
4 22 M 0
5 22 M 0
6 1 M 0
7 1 M 0
8 1 M 0
9 1 M 0
10 1 M 0
11 1 M 0
TABLE PRODUCT_PRICES
product_id price lower_limit usergroup_id
2 39.99 1 0
3 69.99 1 0
4 99.99 1 0
5 124.99 1 0
6 169.99 1 0
7 199.99 1 0
8 249.99 1 0
9 24.99 1 0
10 29.99 1 0
11 34.99 1 0
I want to be able to grab the lowest products price from the category - the function i have currently made is:
function fn_get_category_min_price($category_id)
{
if (!empty($category_id))
{
$product_min_price = db_get_field("SELECT product_id FROM ?:products_categories WHERE category_id = ?i", $category_id);
$category_min_price = db_get_field("SELECT MIN(price) FROM ?:product_prices WHERE product_id = ?i", $product_min_price);
if (!empty($category_min_price))
{
return $category_min_price;
}
else
{
return "";
}
}
return false;
}
but it is not 100% working, although it grabs the price from the right category_id - it does not appear to be grabbing the lowest all the time.... anyone have any ideas or a better way of writing those mysql queries??
As far as I understand, your code takes first product from specified category and then just returns it's price. Sometimes it's minimum, sometimes not.
This can be done with single SQL query:
select min(price) from product_prices p, product_categories c where p.product_id=c.product_id and c.category_id = $category_id
You can do this with an single SQL query by joining the two tables (Natural join):
Select Min(`prize`)
from product_categories natural join product_prices
where category_id = ?i