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.
Related
In the original problem, we have a table that stores the date and win/loss information for each game played by a team.
the matches table
We can use the following SQL statements to get information about the number of games won and lost for each day.
SELECT match_date AS match_date,
SUM(IF(result = 'win',1,0)) AS win,
SUM(IF(result = 'lose',1,0)) AS lose
FROM matches
GROUP BY date;
We store the query results in the matches_2 table.the matches_2 table
My question is, how can we get the matches table based on the matches_2 table with a query?
In the simpler case, we can achieve the task of 'column to row' using union/union all. But that doesn't seem to work in this problem.
All relevant sql code can be found in the following fiddle:
https://dbfiddle.uk/rM-4Y_YN
You can use recursive CTE for this:
WITH RECURSIVE wins (mdate, w) AS
(
SELECT match_date as mdate, 1
FROM matches
WHERE win>0
UNION ALL
SELECT match_date, w + 1 FROM matches
JOIN wins on match_date=mdate
WHERE w < win
),
losses (mdate, l) AS
(
SELECT match_date as mdate, 1
FROM matches
WHERE lose>0
UNION ALL
SELECT match_date, l + 1 FROM matches
JOIN losses on match_date=mdate
WHERE l < lose
)
SELECT mdate as match_date, 'lose' FROM losses
UNION ALL
SELECT mdate as match_date, 'win' FROM wins
See a db-fiddle
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
i have a question. im currently doing an assignment, and having trouble in one particular request.
the request is:
Find Customers who have purchased more than 2 times. Get the
1. customer information
2. purchase frequency
3. total spending
4. avg basket size.
i already got 1 - 3, but i cant do much about number 4.
the values on product can have several values, separated by commas.
~> (product id: 12,4,5) -> if an order buys more than 1 product
i got to the point where i can separate it with length replace, but im a bit confused on how to show it to the average basket size.
thanks for any help!
SQL Table Image
sql table
**Customer**
Customer ID
Name
AddressCity
**Order**
OrderID
CustomerID
ProductID
Total
**Delivery**
DeliveryID
OrderID
AddressCity
this is my current sql statement
SELECT Customer.*, Order.CustomerID,
COUNT(Order.CustomerID) AS PurchaseFrequency,
SUM(Order.Total) AS TotalSpending
FROM Customer JOIN Order
ON Customer.CustomerID=Order.CustomerID
Group By Customer.CustomerID
Having Count(*) > 1
LEN(Order.ProductID) - LEN(REPLACE(Order.ProductID, ',', '')) + 1
Should give you the total amount of products per order.
Just add that to your existing statement.
SELECT Customer.*, Order.CustomerID,
COUNT(Order.CustomerID) AS PurchaseFrequency,
SUM(Order.Total) AS TotalSpending,
AVG(LEN(Order.ProductID) - LEN(REPLACE(Order.ProductID, ',', '')) + 1) as AvgProdQuantityPerOrder
FROM Customer JOIN Order
ON Customer.CustomerID=Order.CustomerID
Group By Customer.CustomerID
Having Count(*) > 1
EDIT:
The fields used in the SELECT part should also be specified in the GROUP BY part. Your query becomes then something like this:
SELECT Customer.CustomerID, Customer.Name, Customer.AdressCity,
COUNT(Order.CustomerID) AS PurchaseFrequency,
SUM(Order.Total) AS TotalSpending,
AVG(LEN(Order.ProductID) - LEN(REPLACE(Order.ProductID, ',', '')) + 1) as AvgProdQuantityPerOrder
FROM Customer JOIN
Order ON Customer.CustomerID=Order.CustomerID
GROUP BY Customer.CustomerID, Customer.Name, Customer.AdressCity
Having Count(*) > 1
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)
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