I want to show it in the first output if the first rank equals 1 in my database
SELECT id, name,password,oldname,number,
RANK() OVER(ORDER BY oldname="mxmx" DESC),
RANK() OVER(ORDER BY number DESC)
as "Rank1"
FROM account
For example like this:
enter image description here
please guide me to reach a conclusion
If you want the first-ranked items to appear first in the results, use:
SELECT
id,
name,
password,
oldname,
number,
RANK() OVER (ORDER BY oldname="mxmx" DESC),
RANK() OVER (ORDER BY number DESC) AS "Rank1"
FROM account
ORDER BY
RANK() OVER (ORDER BY oldname="mxmx" DESC)
Alternatively, you could wrap your original query inside a SELECT * FROM (...) table_alias ORDER BY rank_alias if you prefer. (Though you should select the actual columns you need -- I write the * for brevity only)
PS. Additionally, I found the order of the RANK's themselves returns the results ordered "last-RANK-first", for MySQL 8 at least. Though I can't find a reference that would guarantee this behaviour, your query would be:
SELECT
id,
name,
password,
oldname,
number,
RANK() OVER (ORDER BY number DESC) AS "Rank1",
RANK() OVER (ORDER BY oldname="mxmx" DESC)
FROM account
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 think I just need a little help with this but is there a way to incrementally count steps in SQL using some type of CTE row partition? I'm using SQL Server 2008 so won't be able to use the LAG function.
In the below, I am trying to find a way to calculate the Step Number as pictured below where for each unique ITEM in my table, in this case G43251, it calculates the process Step_Number based on the Date (timestamp) and the process type. For those with the same timestamp & process_type, it would label them both as the same Step_Number as there other fields that could cause the timestamp to repeat twice.
Right now I am playing around with this below and seeing how maybe I could fit in a DISTINCT timestamp methodology ? So that it doesn't count each row as something new.
WITH cte AS
(
SELECT
*,
ROW_NUMBER() OVER (ORDER BY Timestamp_Posted DESC)
- ROW_NUMBER() OVER (PARTITION BY Item ORDER BY Timestamp_Posted Desc) rn
FROM
#t1
)
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY Item, rn ORDER BY Timestamp_Posted DESC) rn2
FROM
cte
ORDER BY
Timestamp_Posted DESC
Please use dense_rank() instead of row_number()
SELECT *, dense_rank() OVER(Partition By Item ORDER BY Timestamp_Posted, Process_Type ) Step_Number
FROM #t1
ORDER BY Timestamp_Posted DESC
I'm trying to use dense_rank() function over the pagename column after the data is ordered by time_id.
Expected output in rank column, rn, is: [1,2,2,3,4].
Currently I wrote it as:
with tbl2 as
(select UID, pagename, date_id, time_id, source--, dense_rank() over(partition by UID order by pagename) as rn
from tbl1
order by time_id)
select *, dense_rank() over(partition by UID order by time_id, pagename) as rn
from tbl2
Any help would be appreciated
Edit 1: What I am trying to achieve here is to give ranks, as per the user on-screen action flow, to the pages that are visited. Suppose if the same page 'A' is visited back after visiting a different page 'B' then the ranks for these page visits A, B, A will be 1,2,3 (note that the same page A has different ranks 1 & 3)
step-by-step demo:db<>fiddle
SELECT
*,
SUM(is_diff) OVER (ORDER BY date_id, time_id, page)
FROM (
SELECT
*,
CASE WHEN page = lag(page) over (order by date_id, time_id) THEN 0 ELSE 1 END as is_diff
FROM mytable
)s
This looks exactly like a problem I asked some years ago: Window functions: PARTITION BY one column after ORDER BY another
You want to execute a window function on columns (uuid, page) but want to keep the current order which is given by unrelated columns (date_id, time_id).
The problem is, that PARTITION BY orders the records before the ORDER BY clause. So, it defines the primary order and this is not expected.
Once I found a solution for that. I adapted it to your used case. Please read the explanation over there: https://stackoverflow.com/a/52439794/3984221
Interesting part: Your special rank() case is not explicitly required in the query, because my solution creates that out-of-the-box ("by accident" so-to-speak ;) ).
Hmmm . . . If you want the pages ordered by their earliest time, then use two levels of window functions:
select t.*,
dense_rank() over (partition by uid order by min_rn, pagename) as ranking
from (select t.*,
min(rn) over (partition by uid, pagename) as min_rn
from t
) t
Note: This uses rn as a convenient shortcut because the date/time is split into two columns. You can also combine them:
select t.*,
dense_rank() over (partition by uid order by min_dt, pagename) as ranking
from (select t.*,
min(date_id || time_id) over (partition by uid, pagename) as min_dt
from t
) t;
Note: This solution is different from S_man's. On your sample data, they do the same thing. However, if the user returns to a page, then his gives page a new ranking. This gives the page the same ranking as the first time it appears. It is not clear what you really want.
You can use DENSE_RANK() like this for your requirment,
SELECT
u_id,
page_name,
date_id,
time_id,
source,
DENSE_RANK()
OVER (
PARTITION BY page_name
ORDER BY u_id DESC
) rn
FROM ( SELECT * FROM tbl1 ORDER BY time_id ) AS result;
I'm writing a query to get the top ten of each area. The query return correctly the ranks, but when I try to get only the top ten, it return an unrecognized name error, even though I declare its name.
with rank as (
select RANK() OVER (PARTITION BY area ORDER BY total_orders_last30days DESC)
FROM `dataset`)
SELECT orders, name, area,
FROM `dataset` where rank<=10
You have multiple problems with your code:
You define a CTE but don't use it.
You have a column in the CTE but don't provide an alias.
You refer to the original dataset, which doesn't have that column.
This is what you want:
WITH r as (
SELECT d.*,
RANK() OVER (PARTITION BY area ORDER BY total_orders_last30days DESC) as rnk
FROM `dataset` d
)
SELECT orders, name, area,
FROM r
wHERE rnk <= 10 ;
select * from
(
Select DISTINCT
DocManREPORT_View.DOCINPUTDATE,
DocManREPORT_View.REACTIVATEDATE,
DocManREPORT_View.TRACENO,
DocManREPORT_View.CLIENTNAME,
DocManREPORT_View.DOCUMENTID,DocManREPORT_View.BARCODEID,
DocManREPORT_View.INPUTMODE,
DocManREPORT_View.INPUTSOURCE,PI.start_time,
RANK() OVER (PARTITION BY process_instance_id
ORDER BY last_modified_date desc) rank,
PI.STATUS AS PROCESSSTATUS
FROM DocManREPORT_View
INNER JOIN PROCESS_INSTANCE PI ON
(pi.instance_id = DocManREPORT_View.process_instance_id)
)
where rank = 1;
I presume DISTINCT clause could screw up the performance. I would recommend you to get rid of it by including into partition by clause and have a look what have you got.
If you can, try to use the
RANK() OVER (PARTITION BY process_instance_id
ORDER BY last_modified_date desc) rank,
Inside the VIEW, since I tihnk the View has already every data to make this step inside.