How to get MAX Hike in Min month? - sql

below is table:
Name | Hike% | Month
------------------------
A 7 1
A 6 2
A 8 3
b 4 1
b 7 2
b 7 3
Result should be:
Name | Hike% | Month
------------------------
A 8 3
b 7 2

Here is one way of doing this:
SELECT Name, [Hike%], Month
FROM
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY [Hike%] DESC, Month) rn
FROM yourTable
) t
WHERE rn = 1
ORDER BY Name;
If you instead want to return multiple records per name, in the case where two or more records might be tied for having the greatest hike%, then replace ROW_NUMBER with RANK.

use correlated subquery
select Name,min(Hike) as Hike,min(Month) as Month
from
(
select * from tablename a
where Hike in (select max(Hike) from tablename b where a.name=b.name)
)A group by Name

You can use something similar to the below:
SELECT Name, MAX(Hike), Month
FROM table
GROUP BY Name, Month
Hope this helps :)

Related

SQL select 1 row out of several rows that have similar values

I have a table like this:
ID
OtherID
Date
1
z
2022-09-19
1
b
2021-04-05
2
e
2022-04-05
3
t
2022-07-08
3
z
2021-03-02
I want a table like this:
ID
OtherID
Date
1
z
2022-09-19
2
e
2022-04-05
3
t
2022-07-08
That have distinct pairs consisted of ID-OtherID based on the Date values which are the most recent.
The problem I have now is the relationship between ID and OtherID is 1:M
I've looked at SELECT DISTINCT, GROUP BY, LAG but I couldn't figure it out. I'm sorry if this is a duplicate question. I couldn't find the right keywords to search for the answer.
Update: I use Postgres but would like to know other SQL as well.
This works for many dbms (versions of postgres, mysql and others) but you may need to adapt if something else. You could use a CTE, or a join, or a subquery such as this:
select id, otherid, date
from (
select id, otherid, date,
rank() over (partition by id order by date desc) as id_rank
from my_table
)z
where id_rank = 1
id
otherid
date
1
z
2022-09-19T00:00:00.000Z
2
e
2022-04-05T00:00:00.000Z
3
t
2022-07-08T00:00:00.000Z
You can use a Common Table Expression (CTE) with ROW_NUMBER() to assign a row number based on the ID column (then return the first row for each ID in the WHERE clause rn = 1):
WITH cte AS
(SELECT ID,
OtherID,
Date,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Date DESC) AS rn
FROM sample_table)
SELECT ID,
OtherID,
Date
FROM cte
WHERE rn = 1;
Result:
ID
OtherID
Date
1
z
2022-09-19
2
e
2022-04-05
3
t
2022-07-08
Fiddle here.

how to get row value with group by clause using subquery in PostgreSQL in Laravel 8?

This is my table, first I want to get status_exec of each MAX (date_sta) and after that I want to grouped by status_exec and get the COUNT.
id_out_sta
status_exec
date_sta
1
2
2021-11-07
1
1
2021-11-28
1
5
2021-12-07
2
7
2021-04-02
2
2
2021-05-12
2
6
2021-08-07
3
2
2021-08-05
3
5
2021-08-28
4
2
2021-03-15
4
5
2021-04-25
The result I would expect should be the following:
status_exec
COUNT
5
3
6
1
This is my query but it didn't help:
SELECT id_out_sta, status_exec , max(date_sta) as max_date_sta
FROM public.status_exe
join public.order_out on status_exe.id_out_sta = order_out.id_out
group by (id_out_sta);
Please any suggestion, query builder or simple query.
A common solution for this is row_number window function to find the maximum of each group. Using this in a CTE and then aggregating the result:
with s as (
select *,
Row_Number() over(partition by id_out_sta order by max_date_sta desc) rn
from t
)
select status_exec, Count(*) "Count"
from s
where rn=1
group by status_exec
Example DB<>Fiddle
Using DISTINCT ON followed by a subquery:
SELECT status_exec, COUNT(*) AS COUNT
FROM
(
SELECT DISTINCT ON (status_exec) *
FROM public.status_exe
ORDER BY status_exec, max_date_sta DESC
) t
GROUP BY status_exec;
Here is another example by using count window function.
SELECT * FROM (
SELECT DISTINCT ON (id_out_sta)
status_exec,
count(*) over(partition by status_exec)
FROM t
ORDER BY id_out_sta, max_date_sta DESC
) as list
GROUP BY 1,2
Fiddle is here

sql - select single ID for each group with the lowest value

Consider the following table:
ID GroupId Rank
1 1 1
2 1 2
3 1 1
4 2 10
5 2 1
6 3 1
7 4 5
I need an sql (for MS-SQL) select query selecting a single Id for each group with the lowest rank. Each group needs to only return a single ID, even if there are two with the same rank (as 1 and 2 do in the above table). I've tried to select the min value, but the requirement that only one be returned, and the value to be returned is the ID column, is throwing me.
Does anyone know how to do this?
Use row_number():
select t.*
from (select t.*,
row_number() over (partition by groupid order by rank) as seqnum
from t
) t
where seqnum = 1;

SQL: Column Sum

Lets have following sample table:
Person Quantity
A 1
B 2
C 3
D 4
E 5
Result should be:
PersonAggregate
1 (0+Quantity of PersonA)=sumA
3 (sumA+Quantity of PersonB)=sumB
6 (sumB+Quantity of PersonC)=sumC
10 (sumC+Quantity of PersonD)=sumD
15 (sumD+Quantity of PersonE)
Is it possible to get this result in onq SQL-query?
Most versions of SQL support cumulative sums as a window function:
select person, sum(quantity) over (order by person) as cumesum
from sample;
You can can also do this with a correlated subquery:
select s.person,
(select sum(s2.quantity)
from samples s2
where s2.person <= s.person
) as cumesum
from sample s;
this will obviously get the individual sums.
select person, sum(quantity)
from sample
group by person
order by person
i don't think your desired effect can be done in a set based way. a procedural language with cursor, like T-SQL or PLSQL, can do it easily.
i'd write a stored procedure and call it.
If the sample table has more than one row per person with multiple quantities that need to be summed you could use:
select curr.person, curr.sum_person + case when prev.person <> curr.person
then prev.sum_person
else 0 end as person_sum
from (select person, sum(quantity) as sum_person
from sample
group by person) curr
cross join (select person, sum(quantity) as sum_person
from sample
group by person) prev
where prev.person =
(select max(x.person) from sample x where x.person < curr.person)
or curr.person = (select min(person) from sample)
group by curr.person
Fiddle: http://sqlfiddle.com/#!2/7c3135/6/0
Output:
| PERSON | PERSON_SUM |
|--------|------------|
| A | 1 |
| B | 3 |
| C | 5 |
| D | 7 |
| E | 9 |
If there is only one row per person on the sample table, you could more simply use:
select curr.person, curr.quantity + case when prev.person <> curr.person
then prev.quantity
else 0 end as person_sum
from sample curr
cross join sample prev
where prev.person =
(select max(x.person) from sample x where x.person < curr.person)
or curr.person = (select min(person) from sample)
group by curr.person
Fiddle: http://sqlfiddle.com/#!2/7c3135/8/0
Output returned is the same, because in your example, there is only one row per person.
If using Oracle, SQL Server, or a database that supports analytic functions, you could use:
If sample has one row per person:
select person,
sum(quantity) over(order by person rows between 1 preceding and current row) as your_sum
from sample
order by person
Fiddle: http://sqlfiddle.com/#!4/82e6f/1/0
If sample has 2+ rows per person:
select person,
sum(sum_person) over(order by person rows between 1 preceding and current row) as your_sum
from (select person, sum(quantity) as sum_person
from sample
group by person) x
order by person
Fiddle: http://sqlfiddle.com/#!4/82e6f/4/0

MAX function without group by

I have the following table:
ID | NUM
1 | 4
2 | 9
3 | 1
4 | 7
5 | 10
I want a result of:
ID | NUM
5 | 10
When I try to use MAX(NUM) I get and error that I have to use GROUP BY in order to use MAX function
Any idea?
As per the error, use of an aggregate like Max requires a Group By clause if there are any non-aggregated columns in the select list (In your case, you are trying to find the MAX(Num) and then return the value(s) associated in the ID column). In MS SQL Server you can get what you want via ordering and limiting the returned rows:
SELECT TOP 1 ID, NUM
FROM [table]
ORDER BY NUM DESC;
In other RDBMS systems the LIMIT offers similar functionality.
Edit
If you need to return all rows which have the same maximum, then use the WITH TIES qualification:
SELECT TOP 1 WITH TIES ID, NUM
FROM [table]
ORDER BY NUM DESC;
May return more than 1 result:
SELECT id, num
FROM table
WHERE num = (SELECT MAX(num) FROM table)
Try this query.
WITH result AS
(
select DENSE_RANK() OVER( ORDER BY NUM desc) AS RowNo,ID,NUM from #emp
)
select ID,NUM from result where RowNo=1
it will return max values even if it has more MAX values like:
ID | NUM
5 | 10
6 | 10
refer below link to know more about RANKING Functions:
http://msdn.microsoft.com/en-us/library/ms189798
How about:
SELECT TOP 1 ID,NUM FROM table ORDER BY NUM DESC;
Do this -
SELECT TOP 1 ID,
NUM
FROM <yourtable>
ORDER BY NUM DESC;
Get all rows have max values but THERE ARE 3 SELECT, It's not good for performance
SELECT id, MAX(num) as num
FROM table
GROUP BY id
ORDER BY MAX(num) DESC
LIMIT (SELECT COUNT(*)
FROM table
WHERE num =(SELECT MAX(num) FROM table)
)