using row_number() in db2 - sql

I have the following data and I am trying to count each record whenever a combo of userid+customerid appear. If the same combo returns in between other combos, I want to start the counter from one again. However, when I use row_number() in the following code in Db2, I can't seem to get it working so that the counter is restarting at 1 for each userid+customerid appearing over time. Does anyone have other suggestions? Thank you so much.
select userid, customer, event_name, event_timestamp,
row_number() over (partition by user_id, customer_number
order by event_timestamp) as steps_rownum
from trackhist
order by userid, event_timestamp;

select userid, customer, event_name, event_timestamp,
row_number() over (partition by userid, customer, grp
order by event_timestamp) as steps
from
(
select t.*,
(row_number() over (order by event_timestamp) -
row_number() over (partition by userid, customer order by event_timestamp)
) as grp
from trackhist t
) t
order by userid, event_timestamp
Output:
Demo here:
Rextester
Note that the demo uses SQL Server, as DB2 is not an option with Rextester (at least for now). The query should work in DB2 however, assuming ROW_NUMBER() behaves the same in both databases.

Related

How to ask another question in one question with rank

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

SQL Server : using CTE row partition to serialize sequential timestamps

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

Rank() based on column entries while the data is ordered by date

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;

BigQuery SQL functions not working properly

I have a problem with functions such as maxif and sumif. When I try to use any of them in my project the console returns 'Function not found: sumif/maxif; Did you mean sum/max?'
It is odd, because function countif works perfectly fine, and both of maxif and sumif are described in the BigQuery documentation, so I'm kind of worried what to do with them in order to run the code properly.
Beneath is a part of my code, any suggestions would be most welcome:
SELECT
DISTINCT *,
COUNTIF(status ='completed') OVER (PARTITION BY id ORDER BY created_at) cpp, --this works
sumif(value,status='completed') OVER (PARTITION BY id ORDER BY created_at) spp, -- this doesn't
maxif(created_at, status = 'completed') OVER (PARTITION BY id ORDER BY created_at DESC) lastpp,
FROM
`production.payment_transactions`
Below is for BigQuery Standard SQL
#standardSQL
SELECT
DISTINCT *,
COUNTIF(status = 'completed') OVER (PARTITION BY id ORDER BY created_at) cpp, --this works
SUM(IF(status = 'completed', value, NULL)) OVER (PARTITION BY id ORDER BY created_at) spp, -- this now works
MAX(IF(status = 'completed', value, NULL)) OVER (PARTITION BY id ORDER BY created_at DESC) lastpp, -- this now works
FROM `production.payment_transactions`
SUMIF() and MAXIF() are not a big query functions. Use a CASE expression:
maxif(case when status = 'completed' then created_at end) over (partition by id order by created_at desc)
This is confusing because the functions are used in other parts of the GCP environment, particularly a component called Dataprep.

How to retriever the First Record and Last Record in the Group, for Same Date, In Oracle SQL

Please Suggest me, I have tried with Partition and group in Oracle SQL, but unable to get the right query
One option uses row_number() twice:
select primary_key, id, created_date
from (
select
t.*,
row_number() over(partition by id, trunc(created_date) order by created_date asc) rn_asc,
row_number() over(partition by id, trunc(created_date) order by created_date desc) rn_desc
from mytable t
) t
where 1 in (rn_asc, rn_desc)