Reputation: 165
I have the following sample data:
car_id owner_id service_date
1 user2 2016-01-02 00:00:00
1 user2 2016-03-02 00:00:00
1 user3 2016-11-02 00:00:00
1 user4 2017-01-02 00:00:00
1 user4 2017-02-12 00:00:00
1 user1 2017-03-22 00:00:00
1 user2 2017-03-24 00:00:00
I am trying to rank owner_id
column for a given car_id
in sql-server
.
For a given car_id
value, the rank column should increase by one, if the 'owner_id' value is different from the 'owner_id' value in the previous row, where rows are sorted by service_date
in ascending order.
Expected Output:
car_id owner_id service_date rnk
1 user2 2016-01-02 00:00:00 1
1 user2 2016-03-02 00:00:00 1
1 user3 2016-11-02 00:00:00 2
1 user4 2017-01-02 00:00:00 3
1 user4 2017-02-12 00:00:00 3
1 user1 2017-03-22 00:00:00 4
1 user2 2017-03-24 00:00:00 5
I tried to find the rank with dense_rank()
function by partitioning over the car_id and owner_id. But it lead to wrong ranks.
CREATE TABLE #tb_example (
car_id INT,
owner_id NVARCHAR(5),
service_date SMALLDATETIME
);
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user2', '2016-01-02');
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user2', '2016-03-02');
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user3', '2016-11-02');
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user4', '2017-01-02');
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user4', '2017-02-12');
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user1', '2017-03-22');
INSERT INTO #tb_example (car_id, owner_id, service_date) VALUES (1, 'user2', '2017-03-24');
SELECT *,
DENSE_RANK() OVER (PARTITION BY car_id, owner_id ORDER BY service_date) AS rnk
FROM #tb_example
ORDER BY service_date;
Upvotes: 1
Views: 158
Reputation: 72165
Try this:
;WITH CTE AS
(
SELECT *,
CASE
WHEN owner_id <> COALESCE(LAG(owner_id) OVER
(PARTITION BY car_id ORDER BY service_date), owner_id)
THEN 1
ELSE 0
END AS grp
FROM #tb_example
)
SELECT *,
SUM(grp) OVER (PARTITION BY car_id ORDER BY service_date) + 1 AS rnk
FROM cte
ORDER BY service_date;
The query uses LAG
to detect changes in owner_id
within the same car_id
partition, with order defined by servic_date
.
Using grp
field we use SUM(grp) OVER ..
to compute rank as a running total of changes.
Upvotes: 1