SQL query to find maximum salary - mysql

I have a table like this
----------------------
| ID | Name | Salary |
| -- | --- | --- |
| 1 | A | 1000 |
| 2 | B | 4000 |
| 3 | C | 5000 |
| 4 | B | 600 |
| 5 | C | 2000 |
| 6 | A | 5000 |
| 7 | B | 4000 |
----------------------
And I want to query the maximum salary in the whole table and the maximum salary of each student. I can write two queries like,
>> SELECT MAX(Salary) FROM TABLE
>> SELECT NAME, MAX(SALARY) FROM TABLE GROUP BY NAME
Now, I want to do the same in a single query without using two queries. How do I approach?

ROLLUP can be used to give an extra row as a 'summary', and so give the overall MAX value...
SELECT name, MAX(salary)
FROM TABLE
GROUP BY name
WITH ROLLUP
ORDER BY GROUPING(name) DESC,
name
Which would yield...
| Name | Salary |
| --- | --- |
| NULL | 5000 |
| A | 5000 |
| B | 4000 |
| C | 5000 |

here is one way:
SELECT NAME, MAX(SALARY) , max(max(salary)) over()
FROM TABLE GROUP BY NAME

You can use GROUP BY to group around the Name field and ORDER BY ... DESC on the Salary field to get the max.
SELECT PrimaryField, MaxField
FROM MyTable
GROUP By PrimaryField
ORDER BY MaxField DESC;
Explanation:
SELECT PrimaryField, MaxField — The fields we want.
FROM MyTable — The table we want.
GROUP By PrimaryField — What we want to be treated as a primary field.
ORDER BY MaxField DESC; — Since we group by PrimaryField, we get only one row for each PrimaryField unique value. If we order the MaxField, we can get the min or max of it as needed.
For you specifically:
SELECT Name, Salary
FROM TABLE
GROUP By Name
ORDER BY Salary DESC;

Related

MYSQL show all entries sorted by 2 columns random on one column

We are looking to return rows of a query as groups and displaying all entries of the group in the sort order. Randomly based on the set_id... and then in order by the sort_id.
So, randomly it will show:
Carl,
Phil,
Wendy,
Tina,
Rick,
Joe
or
Tina,
Rick,
Joe,
Carl,
Phil,
Wendy
This query is always showing Tina/Rick/Joe first
SELECT * FROM products ORDER BY set_id, rand()
Any help would be appreciated
+---------+--------+-------+----------+
| id | set_id | name | sort_id |
+---------+--------+-------+----------+
| 1 | AA |Rick | 2 |
| 2 | BB |Carl | 1 |
| 3 | AA |Joe | 3 |
| 4 | AA |Tina | 1 |
| 5 | BB |Phil | 2 |
| 6 | BB |Wendy | 3 |
+---------+--------+-------+----------+
if you need a random comma separated name list this will do the trick.
This will keep the groups and the correct sorting within the group.
Query
SELECT
GROUP_CONCAT(Table_names_rand.names) as names
FROM (
SELECT
*
FROM (
SELECT
GROUP_CONCAT(name ORDER BY sort_id) as names
FROM
Table1
GROUP BY
set_id
)
AS Table1_names
ORDER BY
RAND()
)
AS Table_names_rand
Result
| names |
|-------------------------------|
| Carl,Phil,Wendy,Tina,Rick,Joe |
or
| names |
|-------------------------------|
| Tina,Rick,Joe,Carl,Phil,Wendy |
demo http://www.sqlfiddle.com/#!9/487ac9/9
if you need random names as records output.
Query
SELECT
Table1.name
FROM
Table1
CROSS JOIN (
SELECT
GROUP_CONCAT(Table_names_rand.names) as names
FROM (
SELECT
*
FROM (
SELECT
GROUP_CONCAT(name ORDER BY sort_id) as names
FROM
Table1
GROUP BY
set_id
)
AS Table1_names
ORDER BY
RAND()
)
AS Table_names_rand
)
AS Table_names_rand
ORDER BY
FIND_IN_SET(name, Table_names_rand.names)
Result
| name |
|-------|
| Carl |
| Phil |
| Wendy |
| Tina |
| Rick |
| Joe |
or
| name |
|-------|
| Tina |
| Rick |
| Joe |
| Carl |
| Phil |
| Wendy |
demo http://www.sqlfiddle.com/#!9/487ac9/28
If we strip away the randomness of the gorup ordering, your query would look like this:
SELECT
*
FROM
products
ORDER BY
set_id,
sort_id;
The ordering by set_id is necessary to "group" the results, without really grouping them. You do not want to group them, because then the rows with the same group would be aggregated, meaning that only one row per group would be put out.
Since you only want to randomize the groups, you need to write another query that assigns a random number to each group, like the one below:
SELECT
set_id,
RAND() as 'rnd'
FROM
products
GROUP BY
set_id
The GROUP BY clause makes sure, that each group is only selected once. The resultset will look like this:
| set_id | priority |
+--------+---------+
| AA | 0.21 |
| BB | 0.1 |
With that result we can then randomize the output, by combining both queries with a JOIN on the set_id field. This will add the randomly generated number from the second query to the result set of the first query and therefore extend the static set_id with the randomized, but still for all group members equal, rnd:
SELECT
products.*
FROM
products
JOIN (
SELECT
set_id,
RAND() as 'rnd'
FROM
products
GROUP BY
set_id
) as rnd ON rnd.set_id = products.set_id
ORDER BY
rnd.rnd,
products.set_id,
products.sort_id;
Keep in mind, that it is important to still group on products.set_id, because it may be possible that two groups get the same random number assigned. If the result would not be ordered by products.set_id those groups members would then be merged.

SQL Query for selecting multiple rows but highest value for each PK

I know that the title sounds horrible but I have no idea how to summarize it better. I'm pretty sure that somebody had the same problem before but I couldn't find anything. RDBMS: MySQL.
Problem:
I have the following (simplified) table:
+------+------------+---------------------------------+
| name | date | score |
+------+------------+---------------------------------+
| A | 01.01.2015 | 1 |
| A | 01.02.2015 | 3 |
| A | 01.03.2015 | 4 |
| B | 01.01.2015 | 3 |
| B | 01.02.2015 | 4 |
| B | 01.03.2015 | 5 |
| C | 01.01.2015 | 1 |
| C | 01.02.2015 | 2 |
| C | 01.03.2015 | 3 |
+------+------------+---------------------------------+
There is no unique constraint or PK defined.
The table represents a highscore of a game. Every day the score of all players are inserted with values that are: name, points, now(),...
The data represent a snapshot of the score of each player at a specific time.
I want the most recent entry for each user only but only for the highest X players. So the result should look like
+------+------------+---------------------------------+
| name | date | score |
+------+------------+---------------------------------+
| A | 01.03.2015 | 4 |
| B | 01.03.2015 | 5 |
+------+------------+---------------------------------+
C doesn't appear since he's not in the top 2 (by score)
A appears with the most recent row (by date)
B appears, like A, with the most recent row (by date) and because he is in the top 2
I hope it becomes clear what I mean.
Thanks in advance!
I understand that what you need is to first select the X players who've gotten the highest score and then get their latest performance. In this case, you should do this:
SELECT *
FROM tablename t
JOIN
(
SELECT t.name, max(t.date) as max_date
FROM tablename t
JOIN
(
SELECT name
FROM
(
SELECT name, max(score) as max_score
FROM table_name
GROUP BY name
) all_highscores
ORDER BY max_score DESC
LIMIT X
) top_scores
ON top_scores.name = t.name
GROUP BY t.name
) top_last
on t.name = top_last.name
and t.date = top_last.date;

select sum of top 10 rows grouped by location column

I have a table of sales paired to the employee that sold it and at which location.
+---------------+----------------------+-----------+-------------+
| Units | location | name | mnt |
+---------------+----------------------+-----------+-------------+
| 5 | abc | bob | 2014-03-01 |
| 3 | abc | tim | 2014-03-01 |
| 4 | xyz | paul | 2014-03-01 |
| 1 | nyc | joe | 2014-03-01 |
+---------------+----------------------+-----------+-------------+
I want to get the stores with the highest sales (sum of units). The query should return the top 10 stores, with the units they sold ordered descending.
I tried this but only got 1 row returned and that too looks wrong.
SELECT * FROM myTable WHERE region='NE' ORDER BY SUM(units) LIMIT 10
FYI: there are additional columns in the table that i have omitted as they dont add much value to the question. One such column is the region column that is in the where clause.
try this
SELECT SUM(units), myTable.* FROM myTable GROUP BY location ORDER BY SUM(units) DESC LIMIT 10
Something like this:
SELECT location, COUNT(Units) FROM myTable WHERE region='NE' GROUP BY location ORDER BY COUNT(Units) LIMIT 10

Select the lastest one of each result in MySQL

Say if I have a table similar to this but including more columns and more rows (These are the only relevant ones):
+-------+----+
| name | id |
+-------+----+
| james | 1 |
| james | 2 |
| james | 3 |
| adam | 4 |
| max | 5 |
| adam | 6 |
| max | 7 |
| adam | 8 |
+-------+----+
How could I get it so that it would only show the max(id) from each name like:
+-------+----+
| name | id |
+-------+----+
| adam | 8 |
| max | 7 |
| james | 3 |
+-------+----+
I currently just have this
"select * from table order by id desc"
but this just shows the latest ids. I only want to be able to see one of each name.
So basically show only the highest id of each name
You would use aggregation and max():
select name, max(id)
from table t
group by name
order by max(id) desc
limit 40;
EDIT:
If you need select * with the highest id, then use the not exists approach:
select *
from table t
where not exists (select 1 from table t2 where t2.name = t.name and t2.id > t.id)
order by id desc
limit 40;
The "not exists" essentially says: "Get me all rows in the table where there is no other row with the same name and a higher id". That is a round-about way of getting the maximum row.
One way to achieve this is to leverage a non-standard GROUP BY extension in MySQL
SELECT *
FROM
(
SELECT *
FROM table1
ORDER BY id DESC
) q
GROUP BY name
-- LIMIT 40
or another way is to grab a max id per name first and then join back to your table to fetch all other columns
SELECT t.*
FROM
(
SELECT MAX(id) id
FROM table1
GROUP BY name
-- LIMIT 40
) q JOIN table1 t
ON q.id = t.id
ORDER BY name;
Output:
| NAME | ID |
|-------|----|
| adam | 8 |
| james | 3 |
| max | 7 |
Here is SQLFiddle demo

How to select from select where group by in MySQL?

I am trying to select and group by column, but keeping other column with all rows. I get error message that #1242 - Subquery returns more than 1 row.
My table
The result I want
Bellow is my query :
SELECT name FROM table WHERE (SELECT pro_id FROM table GROUP BY pro_id)
Try this query:
SELECT Pro_id
, GROUP_CONCAT(Name SEPARATOR ', ') AS Name
FROM MyTable
GROUP BY Pro_ID;
Result:
| PRO_ID | NAME |
-------------------------
| 1 | john, sandra |
| 2 | jeo |
| 3 | bruno, piter |
See this SQLFiddle
You cannot "merge cells" in a SQL result set as you do in your example. The best you could do is either "concat" several values in one "cell" using the GROUP_CONCAT function, or sort the rows to group common values together using ORDER BY clause.
Considering that, you need a very basic SELECT ... ORDER BY statement:
SELECT name, pro_id FROM table ORDER BY pro_id
Producing:
+---------+--------+
| NAME | PRO_ID |
+---------+--------+
| john | 1 |
| sandra | 1 |
| jeo | 2 |
| bruno | 3 |
| piter | 3 |
+---------+--------+
See http://sqlfiddle.com/#!2/6ea716/2