MySQL math to get Top 3 scores - mysql

I'm doing a website for a Fantasy Movie League and what I'm trying to do is get the Top 3 Total Scores overall
Total scores should be: The sum of various points for each players's active movies DIVIDED BY the number of that player's active movies
(So if a player has 300 points from active movies and has 3 active movies, the answer should be 100)
So my question is: How do I calculate the individual player's number of active movies (in the subquery) without specifying the player_id?
SELECT
players.id as player_id,
first_name, last_name,
(metacritic + (imdb*10) + top_bottom + power(receipts,(2/9)) + ticket + oscar_noms + oscar_wins + gg_noms + gg_wins + isa_noms + isa_wins + razzie_noms + razzie_wins + festival_points + ifca_points) / (SELECT COUNT(id) FROM movies WHERE release_date >= CURDATE() and year_id=1 and player_id=4) as player_active_movie_total
FROM movies
INNER JOIN players on players.id=movies.player_id
WHERE release_date >= CURDATE() and year_id=1
ORDER BY player_active_movie_total DESC
LIMIT 3

You don't need a subQuery in your select statement. Based on your criteria you just need to use a GROUP BY statement and a COUNT on ID. The query below will NOT work because you need grouping/sum on each column, but should point you in the right direction
SELECT players.id as player_id, first_name, last_name,
(metacritic + (imdb*10) + top_bottom + power(receipts,(2/9)) + ticket + oscar_noms + oscar_wins + gg_noms + gg_wins + isa_noms + isa_wins + razzie_noms + razzie_wins + festival_points + ifca_points) /
(COUNT(id)) as player_active_movie_total
FROM movies
INNER JOIN players on players.id=movies.player_id
WHERE release_date >= CURDATE() and year_id=1
GROUP BY players.id, first_name, last_name
ORDER BY player_active_movie_total DESC
LIMIT 3
Your metacritic column (and all other in the SELECT list) either need to be part of an aggregate function i.e. SUM or COUNT or MAX or listed in the GROUP BY statement like players.id is. I'm assuming you're wanting some sort of SUM on that entire column

Related

MYSQL: Join list of values into a table

I have list of predefined values Cash, Bank, Card, Cheque called payment modes (no db table for them).
Each payments will have it's mode.
+-----------+
+ Payments +
+-----------+
+ id +
+ amount +
+ date +
+ mode +
+-----------+
The below query will not show mode that are not in the payments table. If for example no payment is made through cheque, then it will not be in the result.
select p.mode, SUM(p.amount) 'total'
from payments p
I also found out about Table Value Constructor but I'm not sure if its supported in MySql as I'm having syntax error.
select p.mode, SUM(p.amount)
from (
VALUES
('Cash'),
('Card'),
('Cheque'),
('Bank')
) as m(name)
left join payments p on m.name = p.mode
group by p.mode
Is there a way to have a query that gets all the mode regardless if they are not present in the payments table? I need a result like:
++++++++++++++++++++
+ mode | total +
++++++++++++++++++++
+ cash | 100 +
+ cheque | 0 +
+ bank | 0 +
+ card | 300 +
++++++++++++++++++++
In MySQL, you can construct the table using union all:
select m.mode, SUM(p.amount)
from (select 'Cash' as mode union all
select 'Card' union all
select 'Cheque' union all
select 'Bank'
) m left join
payments p
on m.mode = p.mode
group by m.mode;
Notes:
I changed name to mode so the column with the same information has the same name.
The group by key needs to be from the first name, not the second (that is m.mode instead of p.mode).
If you want 0 instead of NULL, then use coalesce(sum(p.amount), 0).
You might want to consider a reference table that contains the mode values.
select
m.mode,
SUM(p.amount)
FROM
(
SELECT
m.Cash as mode
FROM
(
VALUES
('cash'),
('card'),
('cheque'),
('bank')
) as m
) as m
left join payments p on m.mode = p.mode
group by
m.mode
You need two aliases and you must use the first value of your array (Cash) in nested select as selected column.
It's worth checking your version of MySQL if the VALUES approach isn't working. It was only introduced from MySQL 8.0.19 , so anyone on an earlier issue will need to use the UNION ALL approach.

MySQL Operand should contain 1 column - how to overcome

I have the following MySQL code:
SELECT company, ((AVG (q1) + AVG(q2) + AVG(q3) ) / 3) AS High,
(SELECT company, ((AVG (q1) + AVG(q2) + AVG(q3) ) / 3)
FROM tresults_new GROUP BY company ASC LIMIT 1) AS Low
FROM tresults_new GROUP BY company DESC LIMIT 1
Now I understand why this brings back the error in the title, as I am bringing back both company and Low in the subquery.
What I am struggling with is how to return both the High and Low (or if you prefer Max and Min) in a single query and I cannot fathom if it is possible and how I would go about it.
Any and all suggestions and feedback welcomed.
For reference, table structure:
company q1 q2 q3
abc 5 6 2
abc 9 5 8
xyz 3 4 6
xyz 3 2 1
zyx 7 9 10
Using the max and min functions should help. I tend to work in SQL Server but this should be true for MySQL as well.
UPDATED AFTER FURTHER CLARIFICATION
So after all the comments on both my response. OPs post and another response. I fiddled around a bit and this should actually get you what you want. It's possibly overblown if you are only doing this once but if your data set grows large this should accomplish what you need and still give you the max and min values that you desire so you know your highest and lowest performing companies. I also did a SQLFiddle if you want to play with it yourself - to be clear I used SQL Server because I'm more familiar in the fiddle example but any changes to MySQL should be relatively trivial.
SELECT vals.company, vals.myval
FROM
(SELECT company, ((AVG (q1) + AVG(q2) + AVG(q3) ) / 3) as myval
FROM tresults_new GROUP BY company
) vals
INNER JOIN
(
SELECT max(myval) val
FROM
(SELECT company, ((AVG (q1) + AVG(q2) + AVG(q3) ) / 3) as myval
FROM tresults_new GROUP BY company
) s
UNION
SELECT min(myval) val
FROM
(SELECT company, ((AVG (q1) + AVG(q2) + AVG(q3) ) / 3) as myval
FROM tresults_new GROUP BY company
) s
) maxmin on maxmin.val = vals.myval
I don't think that you can reasonably avoid two queries or it would be a subquery which leaves you no better off. From your comment and your sample query, I understand that you're just interested in which company has the highest value of AVG(q1)+AVG(q2)+AVG(q3) and which other has the lowest value thereof. In this case I'd just rely on a single query ordered by this value. The first and last rows will be your answer.
SELECT company, val FROM
(SELECT company, AVG(q1) + AVG(q2) + AVG(q3) AS val
FROM tresults_new
GROUP BY company
ORDER BY val DESC LIMIT 1)
AS VAL_MAX
UNION
SELECT company, val FROM
(SELECT company, AVG(q1) + AVG(q2) + AVG(q3) AS val
FROM tresults_new
GROUP BY company
ORDER BY val ASC LIMIT 1)
AS VAL_MIN
or just one query without LIMIT clause and get the first and last rows.
Warning: Of course, it would be tempting to write something like:
SELECT company, MIN(val), MAX(val) FROM
(SELECT company, AVG(q1) + AVG(q2) + AVG(q3) AS val
FROM tresults_new
GROUP BY company)
AS values [GROUP BY company]
without the last GROUP BY company, you'll get the min the max but not the company (this query would be accepted by MySQL but rejected by a number of other RDBMS because you need explicit grouping).
So add the GROUP BY and you'll just get the same values for both min and max which leaves you no better off than your inner query.

find max value in a table with his relative ID

Suppose to have a Table person(ID,....., n_success,n_fails)
like
ID n_success n_fails
a1 10 20
a2 15 10
a3 10 1
I want to make a query that will return ID of the person with the maximum n_success/(n_success+n_fails).
example in this case the output I'd like to get is:
a3 0.9090909091
I've tried:
select ID,(N_succes/(n_success + n_fails)) 'rate' from person
with this query I have each ID with relative success rate
select ID,MAX(N_succes/(n_success + n_fails)) 'rate' from person
with this query just 1 row correct rate but uncorrect ID
How can I do?
MS SQL
SELECT TOP 1 ID, (`n_success` / (`n_success` + `n_fails`)) AS 'Rate' FROM persona
ORDER BY (n_success / (n_success + n_fails)) DESC
MySQL
SELECT `ID`, (`n_success` / (`n_success` + `n_fails`)) AS 'Rate' FROM `persona`
ORDER BY (`n_success` / (`n_success` + `n_fails`)) DESC
LIMIT 1
Lot of answers already. Check working code here on SQL Fiddle with the required output by your last edit.
SELECT `ID`, `n_success` 'rate'
FROM `persona`
ORDER BY (`n_success` / (`n_success` + `n_fails`)) DESC
LIMIT 1
It depends on your dialect of SQL, but in T-SQL it would be:
SELECT TOP 1 p.ID, p.n_success / (p.n_success + p.n_fails) AS Rate
FROM persona p
ORDER BY p.n_success / (p.n_success + p.n_fails) DESC
You can vary as necessary for other dialects (use LIMIT 1 for MySql and SQLite, for example).
select id, (n_success/(n_success + n_fails)) as rate from person
where (n_success/(n_success + n_fails)) =
(select max(n_success/(n_success + n_fails)) from person)

Summary of inner group in a cell in the outer group

I have a section of a report that has an outer group with an inner group. Some of my users will print this report while some will not. I'd like to be able to to keep the toggle capabilities while providing a summary on the outer group of the top 3 rows of the inner group. Basically, I'd like the notes column to see the top three defects and their total counts.
I could accomplish this by doing the work in SQL, but in this case I'd prefer, if possible, for the report server to handle the summary and grouping.
Outer Group Sum(Defects) First(DefectId)
Inner Group Sum(Defects)
Ended up using CTE
with MyCte AS (SELECT
MachineCode + ' | ' + Tool + ' | ' + comments + ' | ' + Operator + ' | ' + convert(nvarchar(50), MinutesDown) + ' ||| ' 'Things',
Reason,
MinutesDown,
PartitionedRowNum = ROW_NUMBER() OVER (PARTITION BY Reason ORDER BY MinutesDown DESC)
from #Comments)
insert into #t
select *
from MyCte
where PartitionedRowNum <= 3

SQL query to get top 10 of a new column generated by SUM

I have a query that looks like so:
SELECT Name, SUM(Price * Quantity) AS Total
FROM Sales
WHERE Date = " + ddItems.SelectedItem + "
GROUP BY Name
How can I show the top 10 totals?
In MySQL the number of rows can be limited with the LIMIT clause, so you can add this to your query to get the top 10:
ORDER BY Total DESC
LIMIT 10