working out a calculation based on two mysql fields - php

I want to work out an average "rating" for my cocktails in a table. There is a tblRating linked to tblCocktail and within this table is "value" and "counter". "value" contains the 1-5 rating a user can give each cocktail, and "counter" contains the value "1". I want to work out the average rating for each cocktail by adding up all the "value"s and dividing it by the number of "counter"s
I've never done mathematical calculations based on php fields before so any help is appreciated
-matt

You probably do not need the counter field, the AVG function can calculate averages without requiring a counter:
SELECT AVG(value)
FROM tblRating
WHERE cocktail_id = 1234
Notes:
You can count the number of rows inside the rating table to determine the number of ratings
NULL values are not taken into account when average is calculated
You must stick with your chosen scale and not allow values outside the 1-5 range

Here's an exaple that should do what you want, obviusly without having the full table schema it is not possible being more accurate, but the example should show the idea :
SELECT c.name, AVG(r.value)
FROM tblCocktail c
JOIN tblRating r ON c.id = r.cocktail.id
GROUP BY c.id, c.name
Basically you are selecting all cocktail from tblCocktail and calculating the average of the rating(r.value).

Related

Average Rating PHP

I structured a PHP table with two columns: 1 for the hospital Id and 1 for the rating.
When a user rates the page, in the Id section goes a default id (depending on the page) and the rating goes in the rating section obv.
Now, how can I calculate the average rating only for a certain ID?
I've never studied Php so I need some help! Thanks everyone!!
You can use AVG on rating column and GROUP BY on hotel_id column.
Can refer below query.
SELECT hotel_id, avg(rating)
FROM hotel_rating
GROUP BY hotel_id;
PS: This is sample query you need to substitute your column names and table names in that

mysql php COUNT by same value in column GROUP BY to echo out

I'm trying to figure out a solution to a query.
Question :
I need to find the sum of rows which have the same value in a certain column. From this I then need to echo out certain bits of information along with the total count each value is seen (i.e. if 'project_id' has two rows with the same value as 11122 then the total count will be 2). I don't know the values I will need as these will be random project numbers in my table.
The column name I need to count by is 'project_id'.
I can't figure out how to echo in the following way:
Project ID = 11122 Total Reviews = 2
Project ID = 99999 Total Reviews = 5
Thanks!
As mentioned above in the comments, Sean's answer works a treat!
SELECT project_id, COUNT(*) as TotalReviews FROM YourTable GROUP BY project_id

How to use ORDER BY and comparing more than 2 columns

So I'm having some problems with an SQL Query, or maybe rather deciding on if I could solve this issue faster in an PHP While loop. See I have a small table with 4 teams, and each team will be assigned a rank based on each teams total points in GOLF,FOOTBALL and Miniature GOLF. The points in the different games: 8 to the first placed team, then 6->4->2 to the other teams depending on score in each game. Then I convert the total score to a ranking number. Here is an example:
MY question and my problem is:
That I don't want two teams to share rank. As you can see team_id 3 and 2 have the same amount of total points, therefor they have rank 3 together. I want to order this table after the team with the highest value in any of the games that have been played. SO! Team 2 has 8 points in one of the games, which is higher then team 3 highest score. So the rank_13 should look like this instead:
I tried to make a query that compares two teams with the same rank_12 point, but I don't know how to compare on 3 columns. Also tried to print the first table out in PHP and then alter the displayed values depending on highest value in the 3 columns, even more confusing. Am I unclear somehow? Please give me a comment.
you can try to order several column seperated by commas and use GREATEST() to find maximum points and compare like this
......order by rank_12 ASC,GREATEST(golf_points,football_points,mini_points)DESC

Using PHP to merge duplicate records from MySQL database in CakePHP

I have a table that stores data that has been entered regarding the amount of waste put in a bin. So my table looks like this:
Material | Weight
===================
Paper | 10
Plastic | 5
Paper | 7
As you can see, I'm going to have duplicate data in the table. At the moment I have multiple instances of different materials, and they all have different weight values attached to them.
Is it possible in PHP to get these duplicate entries, combine them in to one entry, and then display them? So the code would take the 10Kg of Paper and add it to the other instance of paper in the table (7Kg) and then output the value?
I have tried the GROUP BY in MySQL, but all that will do is combine all of the entries and give me the value of the top record, which isn't right.
Thanks!
Use MySql, with a SUM column. This will sum up all values for that column, for each grouping. This is assuming the weight column is just a number (10 instead of 10kg).
SELECT
`material`,
SUM(`weight`) AS `weight`
FROM `material_weights`
GROUP BY `material`
If the weight column isn't just a number (10kg instead of 10), then there will be issues.
If all weights are in KG, then you should just remove the 'kg' value from each weight, and convert the weight column from text into a numeric column.
If there are different kinds of weights (KG, LB, G, etc), then the best way would be to have an extra field in the table, with the weight converted into KG.
Since all your data seems to be in strings, it seems like you would be best served by using a php migration script to examine your data and then combine duplicates. First thing you want to do is determine which Materials have duplicates.
SELECT Material FROM {TABLE} GROUP BY Material HAVING COUNT(*) > 1;
From there you should loop through the materials that come back, and grab all rows with the Material value.
SELECT * FROM {TABLE} WHERE Material = '{$material}';
This will give you all the rows labeled that Material. From there, apply any transformations (just in case there are values labeled g, for example) to the numeric value to ensure you're operating on the same type of value. Then you'd delete all the rows with that type of material. (You have a backup, right?)
DELETE FROM {TABLE} WHERE Material = '{$material}';
Lastly, insert the value you just determined.
INSERT INTO {TABLE} (Material, Weight), ('$material', '$weight');
SELECT
material,
SUM(CAST(REPLACE(weight, 'kg', '') AS UNSIGNED)) AS weightsum
FROM
tbl
GROUP BY
material
You can use the SUM() function with GROUP BY to get the sum of the weight per unique material. In your case, your weight field appears to be a string. You can simply take out the 'kg' from each value using REPLACE, then convert it to an integer, which is then passed to SUM().

MySQL SUM on a query with mutiple values

I have the following query:
$strQuery = "SELECT siteid, SUM(watts) AS wattage, unit, device, time FROM inverter WHERE siteid = '528' AND time Between '$time1' AND '$time2' Order By device Asc";
I'm making a graph in fusion charts and need the total watts for each device but when i do the query above it takes all values and places them for just the first device. I have 40 devices and need each one to have its total watts produced.
On the chart i am displaying device as the x axis name label and the wattage as the value.
Thanks
SUM() is an aggregate function which should be used together with a GROUP statement. If GROUP statement is omitted, all selected rows are aggregated as a group.
see docs: http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html
Look into GROUP BY statement:
SELECT siteid, device,
SUM(watts) AS wattage,
MIN(time) as start_time,
MAX(time) as end_time
unit
FROM inverter
WHERE siteid = '528'
AND time BETWEEN '$time1' AND '$time2'
GROUP BY device, unit
ORDER BY device ASC
Also, when you use aggregation and select fields that are not contained in the GROUP statement (here: time) you must make sure you really get the value you want.
The values of the aggregated row you get for each device are calculated using many rows with possibly individual values in those fields. When you don't use an aggregate function (MIN, MAX, AVG, ..) to determine which of the multiple values your aggregated row should contain, you will receive a value selected more or less selected randomly by MySQL.
You should either
do not select such field, when not necessary. (e.g. time)
use an appropriate aggregate function (MIN, MAX, AVG, ..) for each field that is not contained in the GROUP BY clause to ensure you get the right value. (here i inserted both start and end time for the measure timespan using MIN and MAX)
or include it in the GROUP BY clause
(i did that for "unit" in the example, because you get a wrong result when using SUM on both megawatts and kilowatts .. i assume that is what you use "unit" for?)
Again: Otherwise the resulting value in such fields is random and not deterministic.
You can just use the naive query as proposed by #Kaii and #cairnz.
However, if there are multiple times and units for the devices selected, MySQL will just select a unit and time from one device more or less at random.
Why your query failed
Use are using a aggregate function.
Unless you specify a group by clause the aggregate function will simple add all rows into 1 aggregate.
All the rows not covered in an aggregate function will be condensed into one item (one will simple be chosen at leasure).
In order to see what data lies underneigh, I suggest doing:
SELECT
siteid
, SUM(watts) AS wattage
, GROUP_CONCAT(DISTINCT unit) as units
, device
, GROUP_CONCAT(time) as times
FROM inverter
WHERE siteid = '528'
AND time BETWEEN '$time1' AND '$time2'
GROUP BY device
ORDER BY device ASC
The aggregate function GROUP_CONCAT will show a comma separated list of all (DISTINCT) values lumped together by the aggregation.
Because you are only grouping by device, you will different kinds of units and times will be lumped together.
The more columns you add to the group by clause the more you will "zoom in" on the data and the more rows will be shown.
Why you should be careful in listing 'naked' columns in the select that are not in the group by
If you list 'naked' columns (i.e. not as part of an aggregate expression) that are not listed in the group by clause and these columns are not functionally dependent on the group by clause.
There will be multiple different values, of which only one will be shown.
This behavior is unique to MySQL, most other SQL flavors will issue an error and refuse.
The reason MySQL allows this dangerous behavior is that
A: it allows for faster queries,
B: if you specify a unique key in the group by clause, the other fields will be functionally dependent on that key (cf ANSI SQL 2003) and specifying more fields makes no sense,
C: sometimes you don't care about the values of those other fields and displaying a random representative is what you want.
Why can't I just list all non-aggregate columns in the group by
If you alter the group by statement, this has a profound effect on the output.
The more columns (up until the point where you hit a unique key for the selected columns) you group by, the more details you get, which negates the whole point of using aggregate functions.
The solution
If you just want to show a random unit and time, that's cool of course, but perhaps it makes more sense to use the following query:
SELECT
siteid
, SUM(watts) AS wattage
, COUNT(*) as NumberOfUnits
, device
, MIN(time) as Mintime
, MAX(time) as Maxtime
FROM inverter
WHERE siteid = '528'
AND time BETWEEN '$time1' AND '$time2'
GROUP BY device
ORDER BY device ASC
Creative use of the aggregate functions at your disposal is the answer, see:
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html
Because you're using MySQL, I esp. recommend studying GROUP_CONCAT a very versatile and useful function.
You need to tell what to group by:
SELECT
siteid,
SUM(watts) AS wattage,
unit,
device,
MIN(time) AS StartTime,
MAX(time) AS EndTime
FROM inverter
WHERE siteid = '528' AND time Between '$time1' AND '$time2'
GROUP BY siteid, unit, device
Order By device Asc
EDIT: Using MIN() and MAX() for time allows you to see which timespans the SUM() covers. You should not use time by itself in the query without specifying what time for the sum of wattage for the unit/device combination is showing.

Categories