Average value for top n records? - mysql

i have this SQL Schema: http://sqlfiddle.com/#!9/eb34d
In particular these are the relevant columns for this question:
ut_id,ob_punti
I need to get the average of the TOP n (where n is 4) values of "ob_punti" for each user (ut_id)
This query returns the AVG of all values of ob_punti grouped by ut_id:
SELECT ut_id, SUM(ob_punti), AVG(ob_punti) as coefficiente
FROM vw_obiettivi_2015
GROUP BY ut_id ORDER BY ob_punti DESC
But i can't figure out how to get the AVG for only the TOP 4 values.
Can you please help?

It will give SUM and AVG of top 4. You may replace 4 by n to get top n.
select ut_id,SUM(ob_punti), AVG(ob_punti) from (
select #rank:=if(#prev_cat=ut_id,#rank+1,1) as rank,ut_id,ob_punti,#prev_cat:=ut_id
from Table1,(select #rank:=0, #prev_cat:="")t
order by ut_id, ob_punti desc
) temp
where temp.rank<=4
group by ut_id;

This is not exactly related to the question asked, I am placing this because some one might get benefited.
I got the hackerearth problem to write mysql query to fetch top 10 records based on average of product quantity in stock available.
SELECT productName, avg(quantityInStock) from products
group by quantityInStock
order by quantityInStock desc
limit 10
Note: If someone can make better the above query, please welcome to modify.

Related

get distinct user rows from table while counting a different row

I am trying to count rows from a SQL Table named "reports", sorted by "working" being 0 / 1 / 2.
Currently I have this SQL query which works okay to give me three rows, each with a counter of how many there are that had "working" as either 0 / 1 / 2.
SELECT `working`, COUNT(`working`) AS `total` FROM `reports`
WHERE `appid` = 379720
GROUP BY `working`
ORDER BY `report_id` DESC LIMIT 30
So it currently (correctly as per the SQL) gives me something like:
Working
Total
0
12
1
34
2
18
What I want to do though, is have only one row per user counted, which I can't quite wrap my head around. I can't use a distinct select on an "author_id" field as that ends up included and I can't group by it since I need it grouped by the working int.
To be clear: I want the same results display, but only count one per unique "author_id" from each row.
Any pointers?
You seem to want count(distinct):
SELECT `working`, COUNT(DISTINCT author_id) AS `total`
FROM `reports`
WHERE `appid` = 379720
GROUP BY `working`
ORDER BY `report_id` DESC

How to use SQL MAX(SUM()) function

Hi this is driving me crazy consultation, such as selecting the maximum of this consultation, I made a temporary table to which the maximum then sack him, but quiciera know if the same query can be removed without temporary tables.
I have 2 tables N AND ACCRUED PAYROLL D
Table I occupy the payroll payroll 201314-201320
and table I need the EMPLOYEEIDNO accrued; cod_tiponomina; cod_nomina and accrued employee wages are earned in 14 days;
Good help is that I need to get the maximum of the salary calculation with the sum ();
thanks for the help.
SELECT MAX((SUM(d.devengado) / (COUNT(d.devengado)*14))*30) salario_30dias
FROM devengados d
JOIN nominas n
ON n.cod_nomina = d.cod_nomina
WHERE d.cod_empleado = 564
AND d.cod_tiponomina = 1
AND d.cod_nomina BETWEEN 201314 AND 201320
AND d.devengado > 0
GROUP
BY YEAR(n.fecha_cierre)
, MONTH(n.fecha_cierre);
'Max' and 'Sum' are always executed according to the Group By Clause.
You can nest 2 Selects to get the Maximum of Different Sums:
SELECT MAX(sum) FROM
(SELECT SUM(column) AS sum FROM table GROUP BY crit1)
GROUP BY sum
But a better Way would be to sort the sums, and pick the first one to achieve the same as a sourrounding MIN/MAX (It would not require the nesting of selects):
SELECT SUM(column) AS sum FROM table GROUP BY crit1 ORDER BY sum DESC LIMIT 0,1
(for MIN you would need to sort ASC)

MySQL Rating With Weight

I want to create a rating with weight depending on number of votes.
So, 1 voting with 5 can't be better than 4 votings with 4.
I found this math form:
bayesian = ( (avg_num_votes * avg_rating) + (this_num_votes * this_rating) ) / (avg_num_votes + this_num_votes)
How can I make a MySQL SELECT to get the ID of the best rating image.
I got a table for IMAGE, and a table for VOTING
VOTING:
id
imageID
totalVotes
avgVote
I think I got to do this with SELECT in SELECT, but how?
A first step is to calculate avg_num_votes and avg_rating:
SELECT
SUM(totalVotes)/COUNT(*) AS avg_num_votes,
SUM(avgVote)/COUNT(*) AS avg_rating
FROM voting;
If you can live with a small error, it might be good enough to calculate that once in a while.
Now using your formula and the values above, you can run the weighing query. As a small optimization I precalculate avg_num_votes * avg_rating and call it avg_summand
SELECT
voting.*, -- or whatever fields you need
($avg_summand+totalVotes*avgVote)/($avg_num_votes+totalVotes) AS bayesian
FROM voting
ORDER BY bayesian DESC
LIMIT 1;
Edit
You could run this as a join:
SELECT
voting.*, -- or whatever fields you need
(avg_num_votes*avg_rating+totalVotes*avgVote)/(avg_num_votes+totalVotes) AS bayesian
FROM voting,
(
SELECT
SUM(totalVotes)/COUNT(*) AS avg_num_votes,
SUM(avgVote)/COUNT(*) AS avg_rating
FROM voting AS iv
) AS avg
ORDER BY bayesian DESC
LIMIT 1;
But this will calculate sum and average on every single query - call it a performance bomb.

SQL group by and order by issue

Lets say I have a table - tasks - with the following data:
task user when_added
---------------------------
run 1 2012-08-09
walk 2 2012-08-07
bike 2 2012-08-07
car 1 2012-08-06
run 2 2012-08-06
car 1 2012-08-05
bike 1 2012-08-04
run 1 2012-08-04
As you can see the task is repetitive.
Question is, when i show the data e.g.
select * from tasks group by task order by when_added desc
How does the group by affecting the results? Does 'group by' group them in any order, can I make it?
The reason i ask is that I have a large table which i show data as above and if I lose the group by and just show results in date order, I get some results which do not show on group by, which means the task has been done before but it seems to be grouping by the oldest date and i want the newest date at the top of the pile.
Hope this makes sense...is it possible to affect the group by order?
Is that what you want?
select task, group_concat(user), max(when_added)
from tasks
group by task
order by when_added desc
group by is an aggregate function. In MySQL you can select not aggregates columns anyway, but you should not do that.
If you group by a column then the results will be distinct for that column and all other data will be grouped around it. So there might be multiple data where task is run for instance. Just selecting other columns will select a random result. You should pick a specific result from that group like max or min or sum or concatenate them.

Help with MySQL query... Need help ordering a group of rows

I can tell it best by explaining the query I have, and what I need.
I need to be able to get a group of items from the database, grouped by category, manufacturer, and year made. The groupings need to be sorted based on total amount of items within the group. This part is done with the query below.
Secondly, I need to be able to show an image of the most expensive item out of the group, which is why I use MAX(items.current_price). I thought MAX() gets the ENTIRE row corresponding to the largest column value. I was wrong, as MAX only gets the numeric value of the largest price. So the query doesnt work well for that.
SELECT
items.id,
items.year,
items.manufacturer,
COUNT(items.id) AS total,
MAX(items.current_price) AS price,
items.gallery_url,
FROM
ebay AS items
WHERE
items.primary_category_id = 213
AND
items.year <> ''
AND
items.manufacturer <> ''
AND
items.bad_item <> 1
GROUP BY
items.primary_category_id,
items.manufacturer,
items.year
ORDER BY
total DESC,
price ASC
LIMIT
10
if that doesnt explain it well, the results should be something like this
id 10548
year 1989
manufacturer bowman
total 451
price 8500.00 (The price of the most expensive item in the table/ not the price of item 10548)
gallery_url http://ebay.xxxxx (The image of item 10548)
A little help please. Thanks
I've had this same problem, and I'm fairly certain you have to do two queries (or a subquery, that's a matter of taste).
The first query is like what you have (except id isn't helping you).
The second query uses the GROUP BY fields and one (one!) MAX field to get the id and any other meta-data you need.
I believe this is the implementation, although it's hard to test:
SELECT
items.id,
items.year,
items.manufacturer,
items.gallery_url
FROM
ebay as items
NATURAL JOIN
(
SELECT
COUNT(items.id) AS total,
MAX(items.current_price) AS current_price,
items.primary_category_id,
items.manufacturer,
items.year
FROM
ebay AS items
WHERE
items.primary_category_id = 213
AND
items.year <> ''
AND
items.manufacturer <> ''
AND
items.bad_item <> 1
GROUP BY
items.primary_category_id,
items.manufacturer,
items.year
ORDER BY
total DESC,
price ASC
LIMIT
10
) as bigones
ORDER BY
bigones.total DESC,
bigones.current_price ASC
This documentation may help you understand what's going on:
http://dev.mysql.com/doc/refman/5.1/en/group-by-hidden-columns.html
... all rows in each group should have the same values for the columns that are ommitted from the GROUP BY part. The server is free to return any value from the group, so the results are indeterminate unless all values are the same.