I just start to learn MYSQL and meet a problem like this
So the table is like this:
id name moneySpent
1 Alex 3
2 Alex 1
3 Bill 4
4 Alex 2
5 Alex 1
6 Chris 5
7 Chris 3
Lets say I wanna know the Average money spent per person. I try to do that by using SUM() GROUP BY and AVG() but I got stuck at AVG()
SELECT name, sum(moneySpent) AS total FROM table GROUP BY name;
then this will return
name total
Alex 7
Bill 4
Chris 8
Then how can I get a (7+4+8)/3 using AVG()?
You can get average per person using:
SELECT AVG(total) AS AVERAGE
FROM (SELECT name, sum(moneySpent) AS total
FROM table GROUP BY name) A
;
Output:
AVERAGE
6,3333
You can use inner query to get sum and outer query to derive average from sum as below.
SELECT Avg(sum1) FROM (
SELECT Sum(amount) AS sum1
FROM table1
GROUP BY NAME
) T1
It will generate below output.
AVERAGE_AMOUNT_SPENT
------------------
6.3333
which is what you want to be the output i.e. (7+4+8)/3 = 6.333
You can check demo here
So there are 2 ways to do this, first is use a new table to store the SELECT result. It is much more esay but may take more space.
Second is by jarlh, It comes to me that I do not need to GROUP BY the whole table, I can just add all moneySpent up and divided by distinct name count.
Thanks people!
select avg(total) as average from (SELECT name, sum(moneySpent) AS total FROM table GROUP BY name);
You can use this query to get your desired output
OUTPUT:
AVERAGE
6.3333333333333333
Related
I have a database with one table as shown below. Here I'm trying to write a query to display the names of medication manufactured by the company that manufactures the most number of medications.
By looking at the table we could say the medication names which belongs to the company id 1 and 2 - because those company manufactures the most medication according to this table, but I'm not sure how to write a query for selecting the same i said before.
ID | COMPANY_ID | MEDICATION_NAME
1 1 ASPIRIN
2 1 GLUCERNA
3 2 SIBUTRAMINE
4 1 IBUPROFEN
5 2 VENOFER
6 2 AVONEN
7 4 ACETAMINOPHEN
8 3 ACETAMINO
9 3 GLIPIZIDE
Please share your suggestions. Thanks!
Several ways to do this. Here's one which first uses a subquery to get the maximum count, then another subquery to get the companies with that count, and finally the outer query to return the results:
select *
from yourtable
where companyid in (
select companyid
from yourtable
group by companyid
having count(1) = (
select count(1) cnt
from yourtable
group by companyid
order by 1 desc
limit 1
)
)
SQL Fiddle Demo
This Query might work. I have not tested but the logic is correct
SELECT MEDICATION_NAME
FROM TABLE where
COMPANY_ID=(SELECT
MAX(counted)
FROM ( SELECT COUNT(*) AS counted FROM TABLE ) AS counts);
I'm trying to get the total of votes for each FANOF_ID (ex: Me). The problem is that a FAN can vote each day for the same FANOF_ID (ex: David Bowie RIP)
So each day I could vote for David Bowie as my favorite singer
ID CREATED FAN_ID FANOF_ID
15 2016-01-24 3 3
16 2016-01-25 3 3
17 2016-01-25 2 3
So from that example I should get a result of 2 fans for 'total' for FANOF_ID (3)
This is my actual SQL
SELECT
distinct `fans_fanofvote`.`fan_id`,
COUNT(`fans_fanofvote`.`fanof_id`) AS `total`
FROM `fans_fanofvote`
GROUP BY `fans_fanofvote`.`fanof_id`
ORDER BY `total` DESC
But it returns 3 records even if I use distinct on fan_id it wont work. How can I get mySQL to do a distinct on FAN_ID
My SQL should return one record like that:
FANOF_ID TOTAL
3 2
You want COUNT(DISTINCT). However, you have to be careful about what you are counting (fan_id) and what you are aggregating by (fanof_id):
SELECT fov.fanof_id,
COUNT(DISTINCT fov.fan_id) AS total
FROM fans_fanofvote fov
GROUP BY fov.fanof_id
ORDER BY total DESC;
Note that table aliases make the query easier to read. And don't use back tick unless really needed.
You didn't mention expected output earlier so it was confusing.
SELECT
`fans_fanofvote`.`fanof_id`,
COUNT(`fans_fanofvote`.`fan_id`) AS `total`
FROM `fans_fanofvote`
GROUP BY `fans_fanofvote`.`fanof_id`
ORDER BY `total` DESC
Use count(distinct )
SELECT
COUNT(distinct `fans_fanofvote`.`fanof_id`) AS `total`
FROM `fans_fanofvote`
GROUP BY `fans_fanofvote`.`fanof_id`
ORDER BY `tot
My query is given below:
select vend_id,
COUNT(*) as num_prods
from Products
group by vend_id;
Please tell me how does this part work - select vend_id, COUNT(vend_id) as opposed to select COUNT(vend_id)?
select COUNT(vend_id)
That will return the number of rows where the vendor ID is not null
select vend_id, COUNT(*) as num_prods
from Products
group by vend_id
That will group the elements by Id's, and return, for each Id, how many rows do you have.
An example:
ID name salary start_date city region
----------- ---------- ----------- ----------------------- ---------- ------
1 Jason 40420 1994-02-01 00:00:00.000 New York W
2 Robert 14420 1995-01-02 00:00:00.000 Vancouver N
3 Celia 24020 1996-12-03 00:00:00.000 Toronto W
4 Linda 40620 1997-11-04 00:00:00.000 New York N
5 David 80026 1998-10-05 00:00:00.000 Vancouver W
6 James 70060 1999-09-06 00:00:00.000 Toronto N
7 Alison 90620 2000-08-07 00:00:00.000 New York W
8 Chris 26020 2001-07-08 00:00:00.000 Vancouver N
If you run this query, you will get One row for city, and you can apply a function (in this case, count) to that row. So, for each city, you will get the count of rows. You can also use other functions.
SELECT City, COUNT(*) as Employees
FROM Employee
GROUP BY City
The result is:
City Employees
--------- ---------
New York 3
Toronto 2
Vancouver 3
as you can compare the numbers of rows for each city
When you simply select COUNT(vend_id) with no GROUP BY clause, you get one row with the total count of rows with a non-NULL vendor ID - that last bit is important and is one reason why you may prefer COUNT(*) so as to avoid "missing" rows. Some people may argue that COUNT(*) is somehow less efficient but that's true in no DBMS I've used. In any case, if you are using a brain-dead DBMS, you can always try COUNT(1).
When you group by vend_id, you get one row per vendor ID with the count being the number of rows for that ID.
In step-by-step detail (conceptually, though there are almost certainly efficiencies to be gained by optimising), the first query:
SELECT COUNT(vend_id) AS num_prods FROM products
Get a list of all rows in products.
Count the rows where vend_id is not NULL, then deliver one row containing that count in the single num_prods column.
For the grouping one:
SELECT vend_id, COUNT(vend_id) AS num_prods FROM products GROUP BY vend_id
Get a list of all rows in products.
For each value of vend_id:
Count the rows matching that vend_id where vend_id is not NULL, then deliver one row containing the vend_id in the first column and that count in the second num_prods column.
Note that those rows with a null vend_id do not contribute to the aggregate function (count in this case).
In the first query, that simply means they don't appear in the overall total.
In the second case, it means that the output row still exists but the count will be zero. That's another good reason to use COUNT(*) or COUNT(1).
select vend_id will only select the vend_id field, where select * will select all the fields
select vend_id, COUNT(vend_id) and select COUNT(vend_id) gives same result for the count column as long as you use group by vend_id. when you use select vend_id, COUNT(vend_id) you must group by it using vend_id
I can't seem to find a suitable solution for the following (probably an age old) problem so hoping someone can shed some light. I need to return 1 distinct column along with other non distinct columns in mySQL.
I have the following table in mySQL:
id name destination rating country
----------------------------------------------------
1 James Barbados 5 WI
2 Andrew Antigua 6 WI
3 James Barbados 3 WI
4 Declan Trinidad 2 WI
5 Steve Barbados 4 WI
6 Declan Trinidad 3 WI
I would like SQL statement to return the DISTINCT name along with the destination, rating based on country.
id name destination rating country
----------------------------------------------------
1 James Barbados 5 WI
2 Andrew Antigua 6 WI
4 Declan Trinidad 2 WI
5 Steve Barbados 4 WI
As you can see, James and Declan have different ratings, but the same name, so they are returned only once.
The following query returns all rows because the ratings are different. Is there anyway I can return the above result set?
SELECT (distinct name), destination, rating
FROM table
WHERE country = 'WI'
ORDER BY id
Using a subquery, you can get the highest id for each name, then select the rest of the rows based on that:
SELECT * FROM table
WHERE id IN (
SELECT MAX(id) FROM table GROUP BY name
)
If you'd prefer, use MIN(id) to get the first record for each name instead of the last.
It can also be done with an INNER JOIN against the subquery. For this purpose the performance should be similar, and sometimes you need to join on two columns from the subquery.
SELECT
table.*
FROM
table
INNER JOIN (
SELECT MAX(id) AS id FROM table GROUP BY name
) maxid ON table.id = maxid.id
The problem is that distinct works across the entire return set and not just the first field. Otherwise MySQL wouldn't know what record to return. So, you want to have some sort of group function on rating, whether MAX, MIN, GROUP_CONCAT, AVG, or several other functions.
Michael has already posted a good answer, so I'm not going to re-write the query.
I agree with #rcdmk . Using a DEPENDENT subquery can kill performance, GROUP BY seems more suitable provided that you have already INDEXed the country field and only a few rows will reach the server. Rewriting the query giben by #rcdmk , I added the ORDER BY NULL clause to suppress the implicit ordering by GROUP BY, to make it a little faster:
SELECT MIN(id) as id, name, destination as rating, country
FROM table WHERE country = 'WI'
GROUP BY name, destination ORDER BY NULL
You can do a GROUP BY clause:
SELECT MIN(id) AS id, name, destination, AVG(rating) AS rating, country
FROM TABLE_NAME
GROUP BY name, destination, country
This query would perform better in large datasets than the subquery alternatives and it can be easier to read as well.
OK so I have looked theough the other solutions an no help. So here is what I am trying to do.
I need to select the row with multiple columns where the value in one column is the max value.
here is sample data
orderfileid item number item cost warehouse
1 1234 3.45 ATL
1 2345 1.67 DFW
3 2345 2.45 NYY
3 678 2.4 ORD
2 1234 1.67 DFW
I need to select the entire row where the orderfileid is the max for each unique item number
the returned dataset should look like
orderfileid item number item cost warehouse
2 1234 1.67 DFW
3 2345 2.45 NYY
3 6789 2.4 ORD
I think i tried every combination of select max(orderfileid) i can think of
Any help would be appriciated.
thanks
You need to find your MAX values in a subquery, then use those results to join to your main table to retrieve the columns.
SELECT t.OrderFileId, t.ItemNumber, t.ItemCost, t.Warehouse
FROM YourTable t
INNER JOIN (SELECT ItemNumber, MAX(OrderFileId) AS MaxOrderId
FROM YourTable
GROUP BY ItemNumber) q
ON t.ItemNumber = q.ItemNumber
AND t.OrderFileId = q.MaxOrderId
select
t.*
from
table t
inner join (
select itemnumber, max(orderfileid) maxof
from table
group by itemnumber
) m on t.itemnumber = m.itemnumber
and t.orderfileid = m.maxof
I wouldn't even use Max. Just combine GROUP BY and ORDER BY
SELECT * FROM orders GROUP BY item_number ORDER BY orderfileid DESC
then for minimum just change to ASC
Try
SELECT * FROM `TABLE` WHERE orderfileid=(select max(orderfileid) from TABLE)
you can refer to a similar problem on how to group things using partitioning and picking one per partition in mysql
Deleting Rows: No Single Member Has More Than x Records
this is something similar to doing rank over in Oracle. my previous post was for oracle. my bad..
I think what you are looking for is the "Having" clause. Take a look at this.
select orderfileid, max(itemnumber), itemcost, warehouse from MyTable group by orderfileid having max(itemnumber) ;