I'd like to select the 3 best results of a rank() function for each partition
For instance, in this query :
SELECT id, rank() over (PARTITION BY year order by ...) as rank
FROM table1
GROUP BY year
I'd like to have 3 best ranked for every year.
I can manage that by making a new :
Select *
from ...
where rank <= 3
but then if I have some equalities, i'll get more than 3 row per year.
Do someone have an idea how to solve that ?
We have not much information about your table and query structures, but as a generic solution I'd suggest to add row_number() over (ORDER BY ... desc) as rn and filter by it too with where rn = 1 like here.
Related
Hopefully, someone can help me...
I'm trying to get the last two values from a row_number() window function. Let's say my results contain row numbers up to 6, for example. How would it be possible to get the rows where the row number is 5 and 6?
Let me know if it can be done with another window function or in another way.
Kind regards,
Using QUALIFY:
SELECT *
FROM tab
QUALIFY ROW_NUMBER() OVER(ORDER BY ... DESC) <= 2;
This approach could be further extended to get two rows per each partition:
SELECT *
FROM tab
QUALIFY ROW_NUMBER() OVER(PARTITION BY ... ORDER BY ... DESC) <= 2;
You can use top with order by desc like:
select top 2 row_number() over([partition by] [order by]) as rn
from table
order by rn desc
I'd say #Shmiel is the formal and elegant way, just in case, would be the same as :
WITH CTE AS
(SELECT product,
user_id,
ROW_NUMBER() OVER (PARTITION BY user_id order by product desc)
as RN
FROM Mytable)
SELECT product, user_id
FROM CTE
WHERE RN < 3;
You will use order by [order_condition] with "desc". And then you will use RN(row number) to select as many rows as you want
I prepared query that select date from table. In table I got: rank, name, citycode as columns. When I am doing something like that:
select name, citycode
from tab20
where rank <= 20
I got resault of first 20 rows that gets rank <= 20. And Everything would be ok, but I have to show results of first 20 rows per every citystate. Is it possible to create in one query ? I was tryin union etc but it doesn't work well.
Thanks
You would use the row_number() function. Based on the rank that would be:
select t.*
from (select t.*,
row_number() over (partition by citycode order by rank) as seqnum
from tab20 t
) t
where seqnum <= 20;
I am trying to write a single query (if possible) to rank ids based on multiple conditions.
My table is like this:
id group subgroup value
1 A Q 12
2 A Z 10
3 B Z 14
4 A Z 20
5 B W 20
I tried this query:
SELECT id,
CASE WHEN group = 'A' THEN ROW_NUMBER() OVER (PARTITION BY group ORDER BY SUM(value) DESC) AS rank_group
CASE WHEN group = 'A' AND subgroup = 'Z' THEN ROW_NUMBER() OVER (PARTITION BY group, subgroup ORDER BY SUM(value) DESC) AS rank_subgroup
FROM table
GROUP BY group, subgroup
But ended up with something like this:
id rank_group rank_subgroup
1 1 1
1 2 2
I would like to get each distinct id and return the rank based on the conditions of the case statement, but it looks like adding the needed partition causes a multiplication as the group by is necessary. I could write individual queries for each column, but I'd like to avoid if possible.
Do you want something like this?
select t.*,
dense_rank() over (order by sumg, group),
dense_rank() over (partition by group order by sumsg, subg),
from (select t.*,
sum(value) over (partition by group) as sumg,
sum(value) over (partition by group, subgroup) as sumsg
from t
) t;
This is my best guess at interpreting what you might want.
I have a table called TABLE_SCREW where I want to get the latest records for each code.
For example, in the table below you should obtain the records with ids 3 and 7.
I am a newbie in sql and I hope you can help me.
You could use:
SELECT TOP 1 WITH TIES *
FROM TABLE_SCREW
ORDER BY ROW_NUMBER() OVER(PARTITION BY CODE ORDER BY Date DESC);
Another approach(may have better performance):
SELECT * -- here * should be replaced with actual column names
FROM (SELECT *,ROW_NUMBER() OVER(PARTITION BY CODE ORDER BY Date DESC) AS rn
FROM TABLE_SCREW) sub
WHERE sub.rn = 1;
Group by the highest Number in a column worked great with MAX(), but what if I would like to get the cell that is at most common.
As example:
ID
100
250
250
300
200
250
So I would like to group by ID and instead of get the lowest (MIN) or highest (MAX) number, I would like to get the most common one (that would be 250, because there 3x).
Is there an easy way in SQL Server 2012 or am I forced to add a second SELECT where I COUNT(DISTINCT ID) and add that somehow to my first SELECT statement?
You can use dense_rank to return all the id's with the highest counts. This would handle cases when there are ties for the highest counts as well.
select id from
(select id, dense_rank() over(order by count(*) desc) as rnk from tablename group by id) t
where rnk = 1
A simple way to do what you want uses top and order by:
SELECT top 1 id
FROM t
GROUP BY id
ORDER BY COUNT(*) DESC;
This is a statistic called the mode. Getting the mode and max is a bit challenging in SQL Server. I would approach it as:
WITH cte AS (
SELECT t.id, COUNT(*) AS cnt,
row_number() OVER (ORDER BY COUNT(*) DESC) AS seqnum
FROM t
GROUP BY id
)
SELECT MAX(id) AS themax, MAX(CASE WHEN seqnum = 1 THEN id END) AS MODE
FROM cte;