find max value in a table with his relative ID - mysql

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)

Related

How to count values within a range in my MySQL table

Hello i im trying to count the values within each range e.g. between 115000 - 120000 in my DURATION_IN_MS column.
my column looks like this:
119631
120689
143498
119798
WITH tab1 AS(
SELECT TOP 30 *
FROM MACHINE_PROCESSING_DURATION_EVALUATION
WHERE START_TIMESTAMP BETWEEN '2022-11.10 00:00:00.000' AND '2022-11.10 22:00:00.000')
SELECT(
case
when DURATION_IN_MS BETWEEN 115000 AND 120000 THEN '115000-120000'
when DURATION_IN_MS BETWEEN 120000 AND 125000 THEN '120000-125000'
else 'OTHERS'
END) AS DURATION_IN_MS,
COUNT(*) AS cnt
from tab1
GROUP BY DURATION_IN_MS
my output is like this:
[enter image description here][1]
however, for the range 115000-120000 i wanted to show the count of 8
for the range 120000-125000 i wanted to show the count of 6
Can someone help me ?
ref: fiddle
SELECT
case
when DURATION_IN_MS BETWEEN 115000 AND 120000 THEN '115000-120000'
when DURATION_IN_MS BETWEEN 120001 AND 125000 THEN '120001-125000'
else 'OTHERS'
END AS grp,
COUNT(*) AS cnt
from tab1
GROUP BY grp
Like ysth said in comments, separate the ranges.
The case statement defines the categories as grp, we GROUP BY this and the amount count(*) is per group.
See if you like this technique:
SELECT
FLOOR(DURATION_IN_MS / 5000) * 5000 AS 'bucket start',
FLOOR(DURATION_IN_MS / 5000 + 1) * 5000 - 1 AS 'bucket end',
COUNT(*) AS cnt
FROM MACHINE_PROCESSING_DURATION_EVALUATION
WHERE ...
GROUP BY 1, 2
ORDER BY cnt DESC
LIMIT 30;
It does not match your question exactly but is more flexible in because it automatically creates all the necessary ranges. (Not WITH is needed.)
To get an "other", I might UNION with another query that inverts it. (This is messier.)

How to use SUM and COUNT in sql query

I want to add the total marks of different three table in my database and find the number of students whose marks is less than 80. So I did it this way:
SELECT
(SELECT SUM((totalmarks / 30) * 5) AS marks1 FROM marks) +
(SELECT SUM((totalmarks / 25) * 5) AS marks2 FROM marks2) +
(SELECT SUM((totalmarks / 15) * 5) AS marks3 FROM marks3) AS result
HAVING COUNT((result / 300) * 50) < 80
I am able to get the sum of the marks, but when I put HAVING COUNT condition, it shows nothing. Can someone tell me how to get the number of student using COUNT?
It shows error:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'HAVING COUNT((result/300)*50)>80' at line 11 .
Appreciate if someone can help me with this.
enter image description here
You need to group your results by student:
select studID, sum(result) * 5 as result
from (
select studID, totalmarks / 30 as result from marks1
union all
select studID, totalmarks / 25 as result from marks2
union all
select studID, totalmarks / 15 as result from marks3
) as base
group by studID
having ((result / 300) * 50) < 80
NB: it is a bit strange how you divide and multiply. For example, why not the equivalent:
having result < 480
If the logic is that in marks1 the highest possible score is 30, for marks2 25 and for marks3 15, and you want to give each of the three an equal weighting, then indeed you must divide each of the totalmarks as you do.
After the multiplication with five, this would mean the result can never be more than five.
So the having test is then quite superfluous: all results will be below 480.
So maybe you wanted to see who did not have the perfect score, for which the having clause should then be:
having result < 5
Using your current query, it needs a reference table/container to assess the HAVING condition.. so, here's my suggested solution:
SELECT result
FROM (
SELECT (
SELECT SUM(( totalmarks/30 )*5) AS marks1
FROM marks
) + (
SELECT SUM(( totalmarks/25 )*5) AS marks2
FROM marks2
) + (
SELECT SUM(( totalmarks/15 )*5) AS marks3
FROM marks3
) AS `result`
) AS `derived`
HAVING COUNT((result / 300) * 50) < 80

Make value in a column equals to 1 if it is greater than 1 in mysql

I have a table in my sql.
I have divided the values in count column with the 99th quartile of the column. and I got this result.
id count
1 0.3
2 0.5
3 0.7
4 0.9
5 1.3
6 0.1
7 3.2
the code for calculating the 99th quartile which I used is :
SELECT
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(
GROUP_CONCAT(count ORDER BY count SEPARATOR ','),
',', 100/100 * COUNT(*) + 1), ',', -1) AS DECIMAL) AS `95th Per`
FROM table_name;
and then I did:
select id, (count/(SELECT
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(
GROUP_CONCAT(count ORDER BY count SEPARATOR ',')
,',', 100/100 * COUNT(*) + 1), ',', -1)
AS DECIMAL) AS `95th Per` FROM table_name) as count1
from table_name.
what challange I am facing now is
I want to make count of the column's = 1 whenever the count is greater than 1,
in my case for id=5 and 7
is there any way to tweak my query and get the desired output.
Thanks in advance.
The code for calcluation of the quartile was found on this site
Try wrapping the query in another select similar to
Select
Id,
Case when count > 1 then 1 else count end as count
From (
// place original query here
) t
Then you can manipulate the outer query easier to check for the count. My case syntax may be a bit off but you get the idea.

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.

MySQL math to get Top 3 scores

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