1

I want to generate a sequence for a complex query. For that purpose I have used a variable @rowNo.

My logic is :- If a field - isremoved = 0 then increase row number by 1.
If isremoved = 1 then increase row number by 1 only once till you find next 0.

This is so far I have done, but it gives me syntax error.

DECLARE @rowNo INT;
SET @rowNo = -1;

SELECT
case when sampleTable.isremoved = 0 then @rowNo + 1
    else @rowNo end
as rowNumber,
X,
Y,
Z
.
.
FROM tbl_sample sampleTable
INNER JOIN tbl_sample_2 sample2 ON sampleTable.id = sample2.id
.
.
.

This is my desire output :-

enter image description here

So what is the right way to achieve this kind of functionality in sql server 2012 ?

EDIT :- I do have one solution to use sub query to retrieve row number. But that will hit performance as it is very complex query (more than 20 joins) with huge amount of data. So please suggest me an alternative.

3

3 Answers 3

1

In SQL Server 2012+, you can do what you want with a cumulative sum:

SELECT sum(case when sampleTable.isremoved = 0 then 1 else 0 end) over
            (order by . . .)
       . . .

The order by should repeat the order by in the outer query. You can also try using order by (select null)). In my experience, this uses the ordering of the data in the outer query, but this is not documented to always work.

SQL Server does not allow you to set variables in a SELECT and to return values in a result set. One or the other, but not both.

Sign up to request clarification or add additional context in comments.

Comments

1

one way to do this is with subquery:

Select (Select count(*) from tbl_sample
        where id <= a.id 
            and a.isRemoved =1) rowNumber,
   X, Y, Z
From tbl_sample a
     Join tbl_sample_2 b 
         On b.id = a.id

2 Comments

It is very complex query (almost 20 joins). So This kind of solution hit performance.
Yes, it will, but, assuming one of the id columns is a Foreign Key, if you put an index on it, that will minimize the performance hit.
1

I assume your rowNumber logic is equivalent to: if previous isremoved = 0 then increment rowNumber by 1, otherwise keep it as it is.

Using a combination of LAG and SUM ... OVER you can easily implement this logic:

SELECT id, isremoved,
       SUM(IIF(prevFlag = 0, 1, 0)) OVER (ORDER BY id) AS rowNumber
FROM (
SELECT a.id, isremoved,
       COALESCE(LAG(isremoved) OVER (ORDER BY a.id), isremoved) AS prevFlag
FROM tbl_sample AS a
INNER JOIN tbl_sample_2 AS b ON b.id = a.id) AS t

Demo here

10 Comments

Your solution is right for POC. But it does not work with my actual query. I will get back with exact question soon.
This is the right solution. But there is one issue, I am using order by. That changes row number. Demo here - sqlfiddle.com/#!6/5a30f/2
@unknown I'm not sure I understand what your actual requirement is. If your rows are ordered by seq instead of id then use this field in the OVER clause of the window functions instead of id.
I just want to apply 'order by' on result. Do not confuse with the name seq. Lets assume that there is a name field I am trying to order by. The same would happen.
@unknown This is not possible. It's like wanting to order a single field in two different ways at the same time.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.