Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a view from a cursor in SQL?

I have a table (CheckNumber) with this data:

ID  NumberFrom NumberTo StateID
1   1          10       1
2   2          3        2

This numbers represents physical documents and its states (1 is usable and 2 is unusuable) So now I want to create a document and want to know what number the document will have and what nummbers can be used.

So I have created this cursor.

Declare @numberUsage as table(accountID int,Number Int)
Declare @bankID int
Declare @stateID int
Declare @beginNumber int
Declare @endNumber int
Declare cCursor cursor for Select accountID, stateID, beginNumber,endNumber From Finances.CheckNumber
Open cCursor
Fetch cCursor Into @bankID,@stateID,@beginNumber,@endNumber
While @@FETCH_STATUS = 0
Begin
    Declare @actual int
    Set @actual = @beginNumber
    If @stateID = 1
    Begin
        While @actual <= @endNumber
        Begin
            if not exists(Select Number From Finances.CheckNPayment Where accountID = @bankID and Number = @actual)
            Begin
                Insert Into @numberUsage values(@bankID,@actual)
            End
            Set @actual = @actual + 1
        End
    End
    Else
    Begin
        While @actual <= @endNumber
        Begin
            Delete From @numberUsage Where accountID = @bankID And Number = @actual
            Set @actual = @actual + 1
        End
    End
    Fetch cCursor Into @bankID,@stateID,@beginNumber,@endNumber
End
Close cCursor
Deallocate cCursor
Select * From @numberUsage

The result is this:

accountID Number
1         1
1         4
1         5
1         6
1         7
1         8
1         9
1         10

Is it possible to convert the table result to a view?

like image 697
jcvegan Avatar asked Dec 06 '25 05:12

jcvegan


1 Answers

This will take a few steps, but it's possible. I'll try to explain each piece:

Get a list of sequential numbers:

select row_number() over (order by name) as RN from master..spt_values

If you need more than that, you can cross join to itself and you'll see a lot wider range. Now, you can use this to get your usable range.

;with Nums as (
     select row_number() over (order by name) as RN from master..spt_values)
select *
from Nums n
inner join CheckNumber cn
  on n.RN between cn.NumberFrom and cn.NumberTo

The "with as ()" is called a Common Table Expression (CTE). The link has more info on how it works.

Now we just need to exclude the unusable items. We can use the same idea to generate a list of unusable numbers and then use the EXCEPT keyword.

;with Nums as (
     select row_number() over (order by name) as RN from master..spt_values)
select n.RN
from Nums n
inner join CheckNumber cn
  on n.RN between cn.NumberFrom and cn.NumberTo
where cn.StateId = 1
EXCEPT
select n.RN
from Nums n
inner join CheckNumber cn
  on n.RN between cn.NumberFrom and cn.NumberTo
where cn.StateId = 2

You should be able to adapt this query to your actual data structure and data set fairly easily.

like image 59
Derek Kromm Avatar answered Dec 07 '25 22:12

Derek Kromm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!