I have a table that looks like:
+-------------+--------+------------+
| Employee ID | Salary | Grievances |
+-------------+--------+------------+
| 101 | 70,000 | 12 |
| 102 | 90,000 | 100 |
| ... | ... | ... |
+-------------+--------+------------+
And I want to find all employees who are in the top-ten for salary, but the bottom-five for grievances. I (think I) know how to do this in SQL Server using ROW_NUMBER, but how to do it in MySQL? I've seen the goto question on doing this, but it doesn't really apply to a multiple column ordering.
If I understand correctly, you can do this with a self-join:
select s.*
from (select t.*
from t
order by salary desc
limit 10
) s join
(select t.*
from t
order by grievances asc
limit 5
) g
on s.employeeid = g.employeeid;
Related
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;
table 1 t1
+----+----------+
| id | name |
+----+----------+
| 1 | free |
| 2 | basic |
| 3 | advanced |
+----+----------+
table 2 t2
+----+-------+------+
| id | t1_fk | cost |
+----+-------+------+
| 1 | 2 | 1650 |
| 3 | 3 | 2000 |
| 4 | 2 | 550 |
+----+-------+------+
I want to get the output of t2 table but without duplicates. I was able to get this using GROUP BY function. Also i need the last item on the duplicate (i got stuck here).
Here's what i tried and it didn't work.
SELECT id cost FROM t2 GROUP BY t1_fk ORDER BY MAX(id) DESC
any help
On MySQL 8+, we can use ROW_NUMBER here:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY t1_fk ORDER BY id DESC) rn
FROM t2
)
SELECT id, t1_fk, cost
FROM cte
WHERE rn = 1;
On earlier versions of MySQL, one canonical way to handle this would be to use a join to a subquery which finds the max id value for each t1_fk:
SELECT a.id, a.t1_fk, a.cost
FROM t2 a
INNER JOIN
(
SELECT t1_fk, MAX(id) AS max_id
FROM t2
GROUP BY t1_fk
) b
ON a.t1_fk = b.t1_fk AND a.id = b.max_id;
This is my query:
select location_id, location_name, display_name from location ;
and the result is:
+---------------+------------------------------------+----------------+
| location_id | location_name | display_name |
+---------------+------------------------------------+----------------+
| 1 | L1 PQR MULTIPLEX AND ENTERTAINMENT | L1 PQR |
| 2 | Cinepolis | Cinepolis KP |
| 3 | PVR FORUM MALL | PVR KP |
| 333 | PRASHANTH CINEMAS | PRASHANTH MP |
| 4555 | RAVI CINEMAS | RAVI KP |
| 323213 | ASIAN GPR MULTIPLEX | ASIAN KPHB |
| 5000721013770 | PVR CENTRAL | PVR PUNJAGUTTA |
| 5000721017325 | PVR INORBIT | PVR HITECH |
| 5000981019820 | TIVOLI CINEMAS | TIVOLI SC |
| 5300181011396 | Central Panjaguttaddd | ddd |
+---------------+------------------------------------+----------------+
10 rows in set (0.00 sec)
I also need the count in this query with LIMIT 10 , i have tried as
select count(*) as count, location_id, location_name, display_name from location limit 10;
and the result is:
+-------+-------------+------------------------------------+--------------+
| count | location_id | location_name | display_name |
+-------+-------------+------------------------------------+--------------+
| 50 | 1 | L1 PQR MULTIPLEX AND ENTERTAINMENT | L1 PQR |
+-------+-------------+------------------------------------+--------------+
1 row in set (0.00 sec)
Why it is fetching only one record ??
How can i get the count as well as records ??
The count(*) in the select turns the query into an aggregation query. With no group by, this returns only one row. Actually, in most databases it would return an error because the SQL engine would not know what to do with the remaining columns. In MySQL they get indeterminate values.
If you want the overall count on each row, I would suggest that you use a join to get the result:
select lc.cnt as count, l.location_id, l.location_name, l.display_name
from location l cross join
(select count(*) as cnt from location) lc
limit 10;
If, perchance, you actually want a sequential number on each row, then you are misunderstanding count(). For that, use a variable:
select (#rn := #rn + 1) as count, l.location_id, l.location_name, l.display_name
from location l cross join
(select #rn := 0) vars
limit 10;
You have 2 issues with what you wrote on there.
select count(*) as count, location_id, location_name, display_name from location limit 10;
The first one you shouldn't limit a count!
Second a count is a "group by" instruction it will always give the same UNIQUE number,
What exactly are you trying to resolve?
If you want a 50 on each column (I don't understand why you would want something like that you could do
select (select count(*) from location) as count, location_id, location_name, display_name from location limit 10;
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
so, if i have this table:
| ID | Date | Status | Value |
| 1 | 2-2-2012 | A | 5 |
| 2 | 3-4-2012 | B | 3 |
| 1 | 5-6-2012 | C | 1 |
| 2 | 1-1-2012 | D | 4 |
and I need to get total value and "most recent" status for every IDs, how to do the query? i tried using group by , but the somehow only oldest status shown in the query result.
I need to get the data became like this:
| ID | Date | Status |sum(Value)|
| 2 | 3-4-2012 | B | 7 |
| 1 | 5-6-2012 | C | 6 |
i'm a total newbie in this SQL thing, not an IT person, just because my boss ask to extract some data from our database....
thanks in advance...
Since you have not mentioned any RDBMs, the query below works on almost all RDBMS.
This uses a subquery which separately gets the latest date (assuming that the data type of date is really stored as DATE and not as a string) for every ID. The result of the subquery is then joined back on the table itself in order to get the other columns.
SELECT a.ID, a.Date, a.Status, b.TotalSum
FROM tableName a
INNER JOIN
(
SELECT ID, MAX(date) max_date, SUM(Value) totalSum
FROM tableName
GROUP BY ID
) b ON a.ID = b.ID AND
a.date = b.max_date
SQLFiddle Demo
If you are using mysql then this will work
SELECT id,date,status,sum(value)
FROM (select * from yourTable order by DATE desc ) t
group by ID
order by ID desc