get 2nd highest sum in mysql - mysql

i have table emp :
emp_id quantity
1001 21
1001 10
1002 3
1002 5
1004 4
1004 5
1004 8
i want to get the id having 2nd highest sum
so expected output is
1004 17
let me know how can this be done?
SELECT *,
ROW_NUMBER() OVER(ORDER BY sum_col DESC) as rownum
FROM(
select order_id,
sum(quantity) as sum_col
from order1
group by order_id) t
WHERE t.rownum=2
my query is giving error at line: WHERE t.rownum=2
However if i remove this line it works fine.
Let me know how can i put this condition

WITH cte AS ( SELECT emp_id,
SUM(quantity) `sum`,
DENSE_RANK() OVER (ORDER BY SUM(quantity) DESC) `rank`
FROM test
GROUP BY 1 )
SELECT emp_id, `sum`
FROM cte
WHERE `rank` = 2;
DENSE_RANK() needed (not RANK()) because if, for example, there is 2 rows with highest sum then they'll have RANK and DENSE_RANK equal to 1, but for the next sum value DENSE_RANK will be 2 whereas single RANK will be 3.
fiddle

SELECT emp_id, SUM(quantity) as total_sum FROM emp
GROUP BY emp_id
ORDER BY total_sum DESC
LIMIT 1
OFFSET 1

Try the following one:
SELECT emp_id, SUM(quantity) as total_sum FROM emp
GROUP BY emp_id
ORDER BY total_sum DESC
LIMIT 1,1;

Related

How to select name with the highest power and highest salary

How to select name with the highest power and highest salary
Id
Name
Salary
1
Kobe
50000
2
Lebron
500099
3
Steph
628228
4
Thompson
50505
5
Shabu
393828
The CTE represents your table. The query you need is the last 3 lines, where it's sorting the output by salary in descending order, then limiting to 1 row.
with salaries as (
select 1 as id, 'Kobe' as name, 50000 as salary union all
select 2, 'Lebron', 1000000 union all
select 3, 'Steph', 222222
)
select name
from salaries
order by salary desc limit 1
Output:
Lebron
UPDATE
Per your comment about using a Max function, here's one way, using a sub-query:
select name
from salaries
where salary = (select max(salary) from salaries);
You can use a sub-query to to so
SELECT
t.name
FROM <your_table_name> t
WHERE t.id =
(SELECT
t1.id
FROM
<your_table_name> t1
ORDER BY t1.salary
DESC LIMIT 1);
EDIT
Or you can just use
SELECT
t1.name
FROM
<your_table_name> t1
ORDER BY t1.salary
DESC LIMIT 1
Expanding on 53RT's comment, for MySQL:
SELECT Name
FROM myTable
ORDER BY Salary DESC
LIMIT 1

Show all patients grouped into weight groups. Show the total amount of patients in each weight group. Order the list by the weight group decending

Show all of the patients grouped into weight groups.
Show the total amount of patients in each weight group.
Order the list by the weight group descending.
For example, if they weight 100 to 109 they are placed in the 100 weight group, 110-119 = 110 weight group, etc.
So something like this?
SELECT FLOOR(t.weight/10) * 10 as weightGroup, count(*) as cnt
FROM YourTable t
GROUP BY FLOOR(t.weight/10)
ORDER BY FLOOR(t.weight/10) DESC
I tend to try and avoid expensive floating point functions like FLOOR() or CEIL().
A trick to FLOOR() a number to the next lower integer is to add 0.5 to it and hard-cast it to a signed integer using CONVERT().
WITH
--- some sample data, don't use in final query ...
indata(id,lb) AS (
SELECT 1,101
UNION ALL SELECT 2,102
UNION ALL SELECT 3,103
UNION ALL SELECT 4,104
UNION ALL SELECT 5,105
UNION ALL SELECT 6,106
UNION ALL SELECT 7,107
UNION ALL SELECT 8,108
UNION ALL SELECT 9,109
UNION ALL SELECT 10,110
UNION ALL SELECT 11,111
UNION ALL SELECT 12,112
UNION ALL SELECT 13,113
UNION ALL SELECT 14,114
UNION ALL SELECT 15,115
UNION ALL SELECT 16,116
UNION ALL SELECT 17,117
UNION ALL SELECT 18,118
UNION ALL SELECT 19,119
UNION ALL SELECT 20,120
)
-- real query starts here ...
SELECT
CONVERT ((lb / 10 - 0.5), SIGNED) AS grp
, COUNT(*) AS pat_count
FROM indata
GROUP BY grp
ORDER BY grp DESC;
-- out grp | patcount
-- out -----+----------
-- out 12 | 1
-- out 11 | 10
-- out 10 | 9
This may help
select count (patient_id) as patient_in_group, floor (weight/10)*10 as weight_group
from patients
group by weight_group
order by weight_group desc;
SELECT
count(patient_id),
weight - weight % 10 AS weight_group
FROM patients
GROUP BY weight_group
ORDER BY weight_group DESC
SELECT
COUNT(*) AS patients_in_group,
FLOOR(weight / 10) * 10 AS weight_group
FROM patients
GROUP BY weight_group
ORDER BY weight_group DESC;
SELECT TRUNCATE(weight, -1) AS weight_group,
COUNT(*)
FROM patients
GROUP BY weight_group
ORDER BY weight_group DESC;

MySQL: Find categories of products whose total price is neither maximum nor minimum?

My data:
product Table:
Category_ID Product_ID Price
1 12 120
1 19 234
2 10 129
3 34 145
3 11 100
4 8 56
I would like to find categories whose total price is neither maximum nor minimum using MySQL.
Results:
Category_ID Total_Price
2 129
3 245
I have found this using the following query, but I would like to know if there is any efficient and better query.
SELECT P.Category_ID, SUM(P.Price) AS Total_Price
FROM Product P
GROUP BY P.Category_ID
HAVING SUM(P.Price)
NOT IN
(
(SELECT MAX(Total) FROM (SELECT SUM(Price) AS Total
FROM Product GROUP BY Category_ID) AS T1),
(SELECT MIN(Total) FROM (SELECT SUM(Price) AS Total
FROM Product GROUP BY Category_ID) AS T2)
)
Thank you.
If you are running MySQL 8.0, you can use window functions to rank the categories by ascending and descending price, then filter:
select *
from (
select category_id, sum(price) as sum_price,
rank() over(order by sum(price)) rn_asc,
rank() over(order by sum(price) desc) rn_desc
from product p
group by category_id
) p
where rn_asc > 1 and rn_desc > 1
In earlier versions, one alternative uses subqueries:
select category_id, sum(price) as sum_price
from product p
group by category_id
having sum(price) > (select sum(price) from product group by category_id order by sum(price) limit 1)
and sum(price) < (select sum(price) from product group by category_id order by sum(price) desc limit 1)
This query would benefit an index on (category_id, price).

How to retrieve the values of the table for the max value of two columns in sql

I am trying to query a table by taking the maximum values from two different date columns, and output's all the records that have maximum of both the dates
The table has 6 columns which include st_id(string)(there are multiple entries of the same id), as_of_dt(int) and ld_dt_ts(timestamp). From this table, I am trying to get the max value of as_of_dt and ld_dt_ts and group by st_id and display all the records.
This works perfectly, but its not really optimal
SELECT A.st_id, A.fl_vw, A.tr_record FROM db.tablename A
INNER JOIN (
SELECT st_id, max(as_of_dt) AS as_of_dt, max(ld_dt_ts) AS ld_dt_ts
From db.tablename
group by st_id
) B on A.st_id = B.st_id and A.as_of_dt = B.as_of_dt and A.ld_dt_ts= B.ld_dt_ts
--
The expected result should return the st_id that has the maximum of both as_of_dt and ld_dt_ts i.e., which will be the latest record for each st_id.
Use analytic rank() function. rank() will assign 1 to all records with max date in the st_id partition:
SELECT s.st_id, s.fl_vw, s.tr_record
from
(
SELECT A.st_id, A.fl_vw, A.tr_record,
rank() over(partition by st_id order by as_of_dt desc) rnk_as_of_dt,
rank() over(partition by st_id order by ld_dt_ts desc) rnk_ld_dt_tsrnk
FROM db.tablename A
)s
WHERE rnk_as_of_dt=1 ANDrnk=1 rnk_ld_dt_ts=1 --get records with max dates in both columns
Two ranks can be possibly combined like this:
SELECT s.st_id, s.fl_vw, s.tr_record
from
(
SELECT A.st_id, A.fl_vw, A.tr_record,
rank() over(partition by st_id order by as_of_dt desc, ld_dt_ts desc) rnk
FROM db.tablename A
)s
WHERE rnk=1 --get records with max dates combination
but this is not exactly the same as your original query.
For example if you have this dataset:
st_id, as_of_dt, ld_dt_ts
1 1 2
1 2 1
Then this query
SELECT st_id, max(as_of_dt) AS as_of_dt, max(ld_dt_ts) AS ld_dt_ts
From db.tablename
group by st_id
will return:
st_id, as_of_dt, ld_dt_ts
1 2 2
And final join will not return any rows, because no any row with such combination exist, while query with two ranks combined will return:
st_id, as_of_dt, ld_dt_ts
1 2 1
If such dataset can not exist in your data (say, ld_dt_ts is always>=as_of_dt), then you possibly can combine ranks into single one or even use only one date in the order by.
--I am using row_number() function,--
row_number() over(PARTITION BY st_id ORDER BY as_of_dt DESC, ld_dt_ts DESC) RN
from db.tablename s)tmp where RN=1

How to get the id of highest total from all groups? (MySQL)

Suppose i have following table
id Salary
1 5
2 3
1 3
1 6
2 5
3 5
3 2
4 1
4 3
2 9
I want to get the id of highest total(sum) salary from all groups. In this case the result should be id=2 sum=17( i.e. 3+5+9 = 17)
If you really only expect/need a single id group, then using LIMIT is probably the most straightforward approach here:
SELECT id, SUM(Salary) AS total
FROM yourTable
GROUP BY id
ORDER BY SUM(Salary) DESC
LIMIT 1;
If there could be ties for the highest salary, then we would need to do more work. Before MySQL 8+, the query given by #MKhalid is what we would need to do. Starting with MySQL 8+, we can use the RANK analytic function:
SELECT id, total
FROM
(
SELECT id, SUM(Salary) AS total,
RANK() OVER (ORDER BY SUM(salary) DESC) rank
FROM yourTable
GROUP BY id
) t
WHERE rank = 1;
WITH CTEName AS
(SELECT id, SUM(salary) as total_salary from testTable
GROUP BY id )
select top 1 id from CTEName ORDER BY total_salary desc