I currently have a version number column in my table and all of them are set to one. However, sometimes accounts get closed or reopened and sometimes they may even get updated. I would like to assign a version Number for each new version of the account, which is made possible through the AccountCreatedDate. So anytime the account is created or updated it provides us with an AccountCreatedDate. So the oldest AccountCreatedDate should get a version number 1, the next should get number 2 and so on. How can this be done please provide code on how to accomplish this. I have provided code that groups the same accounts together as the same account will have the same TimeID and I have them in ascending order. How can I give them version numbers? Each record does have its own identity value known as InputRowID
Select * from ods.SchedulePayment
where TimeID IN(
Select TimeID
FROM ods.SchedulePayment
GROUP BY TimeID
HAVING COUNT(*) >1
)ORDER BY TimeID, AccountCreatedDate
I think you want row_nubmer():
select sp.*,
row_number() over (partition by TimeID order by AccountCreatedDate) as version_number
from ods.SchedulePayment sp;
If you want to update the value, then:
with toupdate as (
select sp.*,
row_number() over (partition by TimeID order by AccountCreatedDate) as new_version_number
from ods.SchedulePayment sp
)
update toupdate
set version_number = new_version_number
where version_number <> new_version_number or version_number is null;
Row_number() is what you should opt for
Select *, row_number() over (partition
by
Account order by accountcreationdate
asc) from ods.SchedulePayment
where TimeID IN(
Select TimeID
FROM ods.SchedulePayment
GROUP BY TimeID
HAVING COUNT(*) >1
)ORDER BY TimeID,
AccountCreatedDate
Related
I have a table that contains three columns: ACCOUNT_ID, STATUS, CREATE_DATE.
I want to grab only the LAST status for each account_id based on the latest create_date.
In the example above, I should only see three records and the last STATUS per that account_2.
Do you know a way to do this?
create table TBL 1 (
account_id int,
status string,
create_date date)
select account_id, max(create_date) from table group by account_id;
will give you the account_id and create_date at the closest past date to today (assuming create_date can never be in the future, which makes sense).
Now you can join with that data to get what you want, something along the lines for example:
select account_id, status, create_date from table where (account_id, create_date) in (<the select expression from above>);
If you use that frequently (account with the latest create date), then consider defining a view for that.
If you have many columns and want keep the row that is the last line, you can use QUALIFY to run the ranking logic, and keep the best, like so:
SELECT *
FROM tbl
QUALIFY row_number() over (partition by account_id order by create_date desc) = 1;
The long form is the same pattern the Ely shows in the second answer. But with the MAX(CREATE_DATE) solution, if you have two rows on the same last day, the IN solution with give you both. you can also get via QUALIFY if you use RANK
So the SQL is the same as:
SELECT account_id, status, create_date
FROM (
SELECT *,
row_number() over (partition by account_id order by create_date desc) as rn
FROM tbl
)
WHERE rn = 1;
So the RANK for, which will show all equal rows is:
SELECT *
FROM tbl
QUALIFY rank() over (partition by account_id order by create_date desc) = 1;
select * from
(select Id, Prodcut, Billing_date
, row_number() over (partition by Id, product order by Billing_date desc) as RowNumber
,sum(Revenue)
from Table1
group by 1,2,3,4,1) a
where a.rowNumber = 1
There are rows where Id+product combination repeats for latest billing date and which causing some data to be missed out. I am trying to add sum with row_number to sum all the ID&product combinations for the latest date but not able to make it work.
Can anyone please help me out here!
Data Sample Image
Database: Athena, Dbeaver
I would expect this to do what you want:
select *
from (select Id, Product, Billing_date,
row_number() over (partition by Id, product order by Billing_date desc) as seqnum,
sum(Revenue)
from Table1
group by Id, Product, Billing_date
) t1
where seqnum = 1;
Your group by columns do not seem correct. I'm surprised your query runs in any datbase.
I'm currently working on a SQL query that searches an "archive" database and returns a row for each change that occurred on an order from the beginning of time to today.
What I would like to do with this query is only return the orders that are currently or have been associated with a specific order handler. The best way for me to explain it is that every order is currently grouped in a "set" with a row number for each change, but if one of the rows ever holds the value I'm looking for either "handler" columns, I want it to return all the rows, not just the one with that target value.
Here is what I have so far.
SELECT
ROW_NUMBER() OVER (PARTITION BY OrderId ORDER BY EventDateTime) AS RowNumber,
ace.[OrderId],
ace.[OrderHandler],
ace.[EventDateTime],
ace.[OrderStatus],
LAG(ace.[OrderHandler], 1) OVER (PARTITION BY [OrderId] ORDER BY ace.[EventDateTime]) AS PreviousOrderHandler,
LAG(ace.[EventDateTime], 1) OVER (PARTITION BY [OrderId] ORDER BY ace.[EventDateTime]) AS PreviousEventDateTime,
LAG(ace.[OrderStatus], 1) OVER (PARTITION BY [OrderId] ORDER BY ace.[EventDateTime]) AS PreviousOrderStatus
FROM
Archive AS ace
Here is the sample data I receive when running the above query:
So instead of just returning row number 9 where the OrderHandler = POOL, I want to query if the OrderId has an OrderHandler of POOL at ANY TIME in history, return all the rows.
I figured I could potentially use a WHERE EXISTS but I'm not sure how I could return the whole set of results instead of just the results that match.
Any help is extremely appreciated!
You can use exists like this:
select a.*
from ace a
where exists (select 1
from ace a2
where a2.orderid = a.orderid and
a2.orderhandler = #orderhandler
);
Script for solution:
SELECT ROW_NUMBER() OVER (PARTITION BY ace.OrderId ORDER BY ace.EventDateTime) AS RowNumber
,ace.[OrderId]
,ace.[OrderHandler]
,ace.[EventDateTime]
,ace.[OrderStatus]
,LAG(ace.[OrderHandler], 1) OVER ( PARTITION BY ace.[OrderId] ORDER BY ace.[EventDateTime] ) as PreviousOrderHandler
,LAG(ace.[EventDateTime], 1) OVER ( PARTITION BY ace.[OrderId] ORDER BY ace.[EventDateTime] ) as PreviousEventDateTime
,LAG(ace.[OrderId], 1) OVER (PARTITION BY ace.[OrderId] ORDER BY ace.[OrderId] ) as PreviousOrderId
,LAG(ace.[OrderStatus], 1) OVER ( PARTITION BY ace.[OrderId] ORDER BY ace.[EventDateTime] ) as PreviousOrderStatus
FROM Archive as ace
WHERE EXISTS
(SELECT * FROM
(
SELECT ROW_NUMBER() OVER (PARTITION BY OrderId ORDER BY EventDateTime) AS RowNumber
,ace.[OrderId]
,ace.[OrderHandler]
,ace.[EventDateTime]
,ace.[OrderStatus]
FROM Archive as ace
GROUP BY ace.[OrderId]
,ace.[OrderHandler]
,ace.[EventDateTime]
,ace.[OrderStatus]
HAVING ace.OrderHandler LIKE '%POOL%'
)x
WHERE ace.OrderId = x.OrderId)
I have a table with multiple rows of the same member id. I need only distinct rows based on 2 unique columns
Ex: there are 100 different customers, the table has 1000 rows because every customer has multiple cities and segments assigned to him.
I need 100 distinct rows for these customers depending on a unique segment and city combination. There is no specific requirement for this combination, just the first from the table is fine.
So, currently the table is somewhat like this,
Hope this helps.
use row_number()
select * from (select *,row_number() over(partition by memberid order by sales) rn
from table_name
) a where a.rn=1
Handy sql-server top(1) with ties syntax for that
select top(1) with ties t.*
from table_name t
order by row_number() over(partition by memberid order by sales)
As you have no paticular requirement for which exactly row to select, any column will do at order by, it can be null as well
select top(1) with ties t.*
from table_name t
order by row_number() over(partition by memberid order by (select null))
The simplest way to do this is to use the ROW_NUMBER() OVER(GROUP BY...) syntax. You have no need to use an order by, since you want an arbitrary row, but only one, for each member.
Since you need only the expected data, and not the Row_Number value, make sure that you detail the fields returned, like below:
SELECT
MemberId,
city,
segment,
sales
FROM (
SELECT *
ROW_NUMBER() OVER (GROUP BY MemberId) as Seq
FROM [Status]
) src
WHERE Seq = 1
This question already has an answer here:
SQL Server query assistance needed
(1 answer)
Closed 6 years ago.
I have a UNION ALL query that I'm getting incorrect results for. I'm supposed to get about 1100 hundred records. Please see query...
select
Pop, planID, PopFull, ApptDate, intake1,FollowUP2,FollowupCode, rn, '5133'
from
(Select *, row_number() over (partition by planID order BY AddedDate asc) as rn from Vinfo) t
where
rn = 1 and ApptDate >='12/1/2014' and ApptDate <='12/31/2015'
Union All
select
Pop, planID, PopFull, ApptDate, intake1, FollowUP2, FollowupCode, rn, '5133'
from
(Select *,row_number() over (partition by PlanID order BY AddedDate DESC) as rn from Vinfo) t
where
rn = 1 and ApptDate >='12/1/2014' and ApptDate <='12/31/2015'
So what I'm trying to do is SELECT all the info and in the first SELECT statement, I'm trying to get a VALUE for INTAKE when ADDEDDATE is the lowest (earliest).
I'm doing the UNION all because in the second SELECT statement, I'm trying to get a value for FOLLOWup when ADDEDDATE is the oldest (most recent).
The values for INTAKE AND FOLLOWUP might be different, but doesnt have to be. I'm trying to track the difference.
However when I run this query, I get double the records. Is there a way for me to run this query so that I can get the correct number of records (1100) and get value for INTAKE and if there's a change in value for FOLLOWUP I will see that in the same row?
Instead of seeing double of everything. Basically the way it's running now is if PLANID is 1023 and Intake for EARLIEST date is B then it will show me B for FollowUP as well. in Addition if, FollowUP for LATEST date is C then it will show me C for Intake and FollowUP in the row below it.
EDIT:
select Pop,planID,PopFull,ApptDate, intake1,FollowUP2,FollowupCode, '5133'
from (select *,
row_number() over (partition by planID order BY AddedDate asc) as rn_first,
row_number() over (partition by PlanID order BY AddedDate DESC) as rn_last
from VInfo
) t
where t.rn_first = 1 or rn_last = 1
and ApptDate >='12/1/2014' and ApptDate <='12/31/2015'
Ran this but doesn't give right results
You will obviously get duplicates for those rows which have only one instance of Pop, planID, PopFull, ApptDate, intake1, FollowUP2, FollowupCode combination - i.e. both ASC and DESC return one row and rn=1 for ASC and DESC sorting.
UNION ALL does allow duplicates from top and bottom rowsets.
You may try UNION instead.
Also, as suggested before, you may count both ROW_NUMBERS in single select:
select *
from
(
select v.*,
row_number() over (partition by PlanID order BY AddedDate asc) as rn_first,
row_number() over (partition by PlanID order BY AddedDate DESC) as rn_last
from Vinfo v
) t
where t.rn_first = 1 or rn_last = 1