Cursor never ending in T-SQL - tsql

I have problems with a cursur that’s ends randomly. I want to produce a row for each element , so for every element there is a row for every month in 2012. If there is a row missing for a specific month, it should create that as well.
Now, it’s producing a row for the last element in every month until year 2057.
Now, I have a row for each element until in every month until year 2057 and only for one element in my table.
My table design:
create table tblDataUpdateTest
(
slno int identity(1,1),
cName varchar(50),
cRemarks varchar(50),
[Date] date,
)
insert into tblDataUpdateTest (cName, cRemarks,[Date]) values ('name1','Text1','2012-01-01'),
('name2','Text2','2012-01-01')
My code:
declare #y as int
declare #d as int
SET #y = 2012
SET #d = 1
Declare ##counter int
Declare ##month int
set ##counter=0
Declare ##slno int
Declare ##cRemarks varchar(100)
Declare ##cName varchar(50)
Declare ##Date date
set ##month = 1
Declare tmepTbl cursor
For
Select slno,cName,cRemarks,date from tblDataUpdateTest
Open tmepTbl /* Opening the cursor */
fetch next from tmepTbl
into ##slno,##cName,##cRemarks,##Date
while ##fetch_Status=-1
begin
if not exists (select cRemarks from tblDataUpdateTest where MONTH(Date) = ##month AND YEAR(Date) = 2012)
begin
insert into tblDataUpdateTest (cName, cRemarks,[Date]) values (##cName,'s',(DateAdd(yy, 2012-1900,DateAdd(m, ##month - 1, 01 - 1))))
end
fetch next from tmepTbl
into ##slno,##cName,##cRemarks,##Date
set ##month=##month+1
end
close tmepTbl
Deallocate tmepTbl
My table now
cName cRemarks Date
name1 Text1 2012-01-01
name2 Text2 2012-01-01
I want follwing to happen:
cName cRemarks Date
name1 Text1 2012-01-01
name1 Text1 2012-02-01
name1 Text1 2012-03-01
name2 Text2 2012-01-01
name2 Text2 2012-02-01
name2 Text2 2012-03-01
and so on.
Thanks!

Wouldn't be better to use a recursive CTE, instead of a cursor?
Here is an example:
DECLARE #y INT
DECLARE #m INT
DECLARE #n INT
SET #y = 2012
SET #m = 1
SET #n = 3
;WITH dates(d, m) AS(
SELECT CONVERT(DATE, CONVERT(VARCHAR(4), #y) + '-01-01'), 1
UNION ALL
SELECT CONVERT(DATE, CONVERT(VARCHAR(4), #y) + '-' + CASE WHEN m + 1 < 10 THEN '0' ELSE '' END + CONVERT(VARCHAR(2), m + 1) + '-01')
, m + 1
FROM dates
WHERE m < #n
)
INSERT INTO tblDataUpdateTest(cName, cRemarks,[Date])
SELECT cName, cRemarks, [date] FROM (
SELECT cName, cRemarks, dates.d AS [date]
FROM tblDataUpdateTest
CROSS JOIN dates) t
WHERE NOT(EXISTS(SELECT * FROM tblDataUpdateTest WHERE cName = t.cName AND [date] = t.[date]))
OPTION(MAXRECURSION 11)
SELECT * FROM tblDataUpdateTest ORDER BY cName

Related

Generate Row number Automatically if only one Record is fetching

ALTER PROCEDURE [dbo].[SerailNo_LoadValue]
(
#SerialNo int,
#Season nchar(5)
)
AS
BEGIN
IF EXISTS (SELECT 1 FROM MATERIAL_Stock WHERE SerialNo = #SerialNo and Season = #Season)
BEGIN
if(#Season = 'PER')
BEGIN
SELECT material_code,ULC_id,setNo,MONTH(GETDATE())AS Delivery_Month,YEAR(GETDATE())AS Delivery_Year,1 AS NORECORD
,ISNULL(qty_total,0) AS qty_total,ISNULL(ULC,0) AS 'ulsmtr',isnull(MATNR,'') as MATNR --ADDED BY LALIT AS DISCUSSED WITH DIPENDRA ON 22 APRIL 2016
FROM MATERIAL_Stock LEFT JOIN ULC_master ON ULC_master.ID =MATERIAL_Stock.ULC_id WHERE SerialNo = #SerialNo and Season = #Season
END
ELSE
BEGIN
SELECT material_code,ULC_id,setNo,Delivery_Month,Delivery_Year,1 AS NORECORD
,ISNULL(qty_total,0) AS qty_total,ISNULL(ULC,0) AS 'ulsmtr',isnull(MATNR,'') as MATNR --ADDED BY LALIT AS DISCUSSED WITH DIPENDRA ON 22 APRIL 2016
FROM MATERIAL_Stock LEFT JOIN ULC_master ON ULC_master.ID =MATERIAL_Stock.ULC_id WHERE SerialNo = #SerialNo and Season = #Season
END
select distinct Delivery_Year, Delivery_Month, Season into #T from Material_stock
where Season=#Season
order by Delivery_Year,Delivery_Month
select *,ROW_NUMBER() OVER (ORDER BY Delivery_Year,Delivery_Month) AS RowNumber into #TT from #T
declare #MONTH int
declare #YEAR int
declare #ROWID int
select top 1 #MONTH=Delivery_Month,#YEAR=Delivery_Year from dbo.Material_stock where Season=#Season And SerialNo=#SerialNo
select #ROWID=RowNumber from #TT where Delivery_Month=#MONTH and Delivery_Year=#YEAR
select Delivery_Year as Delivery_Month1 , Delivery_Month, Delivery_Year, Season,RowNumber from #TT where RowNumber>=#ROWID
drop table #T
drop table #TT
END
END

Can I insert a dynamic number of rows into a table using values from the table?

I want to insert a dynamic number of rows into a table, based on information in that table.
I can do it using the code below, but I'm wondering if there's a way to avoid the loop.
The commented out section was my best attempt at what I was trying to do, but it gave me an error of:
"The reference to column "iCount" is not allowed in an argument to a TOP, OFFSET, or FETCH clause. Only references to columns at an outer scope or standalone expressions and subqueries are allowed here."
DECLARE #TableX TABLE (
TDate DATE
, TType INT
, Fruit NVARCHAR(20)
, Vegetable NVARCHAR(20)
, Meat NVARCHAR(20)
, Bread NVARCHAR(20)
)
INSERT INTO #TableX VALUES
('2016-11-10',1,'Apple','Artichoke',NULL,NULL)
, ('2016-11-10',1,'Banana','Beet',NULL,NULL)
, ('2016-11-10',1,'Canteloupe','Cauliflower',NULL,NULL)
, ('2016-11-10',1,'Durian','Daikon',NULL,NULL)
, ('2016-11-10',2,NULL,NULL,'Rabbit','Rye')
, ('2016-11-10',2,NULL,NULL,'Sausage','Sourdough')
, ('2016-11-11',1,'Elderberry','Eggplant',NULL,NULL)
, ('2016-11-11',2,NULL,NULL,'Turkey','Tortilla')
, ('2016-11-11',2,NULL,NULL,'Venison','Vienna')
SELECT * FROM #TableX
DECLARE #BlankRow TABLE (
ID INT IDENTITY
, TDate DATE
, TType INT
, iCount INT
)
DECLARE #Counter1 INT = 0
, #RowCount INT
; WITH BR1
AS (
SELECT TDate, TType, COUNT(*) AS iCount
FROM #TableX
WHERE TType = 1
GROUP BY TDate, TType
)
, BR2
AS (
SELECT TDate, TType, COUNT(*) AS iCount
FROM #TableX
WHERE TType = 2
GROUP BY TDate, TType
)
INSERT INTO #BlankRow
SELECT ISNULL(BR1.TDate, BR2.TDate) AS TDate,
CASE WHEN ISNULL(BR1.iCount,0) < ISNULL(BR2.iCount,0) THEN 1 ELSE 2 END AS TType,
ABS(ISNULL(BR1.iCount,0) - ISNULL(BR2.iCount,0)) AS iCount
FROM BR1
FULL JOIN BR2
ON BR1.TDate = BR2.TDate
WHILE #Counter1 < (SELECT MAX(ID) FROM #BlankRow)
BEGIN
SET #Counter1 += 1
SET #RowCount = (SELECT iCount FROM #BlankRow WHERE ID = #Counter1)
INSERT INTO #TableX
SELECT TOP (#RowCount) tx.TDate, br.TType, NULL, NULL, NULL, NULL
FROM #TableX tx
LEFT JOIN #BlankRow br
ON tx.TDate = br.TDate
WHERE br.ID = #Counter1
END
/*INSERT INTO #TableX
SELECT TOP (tx.iCount) tx.TDate, br.TType, NULL, NULL, NULL, NULL
FROM #TableX tx
JOIN #BlankRow br
ON tx.TDate = br.TDate*/
SELECT *
FROM #TableX
ORDER BY TDate, TType,
ISNULL(Fruit,REPLICATE(CHAR(255),20)),
ISNULL(Vegetable,REPLICATE(CHAR(255),20)),
ISNULL(Meat,REPLICATE(CHAR(255),20)),
ISNULL(Bread,REPLICATE(CHAR(255),20))
The data is silly, I know, but my end goal is to have two different Tablix's in ReportBuilder that end up with the same number of rows so the headers of my groups show up at the same place on the page.
Something like this:
declare #TableX table(TDate date
,TType int
,Fruit nvarchar(20)
,Vegetable nvarchar(20)
,Meat nvarchar(20)
,Bread nvarchar(20)
);
insert into #TableX values
('2016-11-10',1,'Apple','Artichoke',NULL,NULL)
,('2016-11-10',1,'Banana','Beet',NULL,NULL)
,('2016-11-10',1,'Canteloupe','Cauliflower',NULL,NULL)
,('2016-11-10',1,'Durian','Daikon',NULL,NULL)
,('2016-11-10',2,NULL,NULL,'Rabbit','Rye')
,('2016-11-10',2,NULL,NULL,'Sausage','Sourdough')
,('2016-11-11',1,'Elderberry','Eggplant',NULL,NULL)
,('2016-11-11',2,NULL,NULL,'Turkey','Tortilla')
,('2016-11-11',2,NULL,NULL,'Venison','Vienna');
with DataRN as
(
select *
,row_number() over (partition by TDate, TType order by TDate) rn
from #TableX
)
,RowsRN as
(
select tt.TDate
,tt.TType
,td.rn
from (select distinct TDate, TType
from #TableX
) tt
full join (select distinct t1.TDate
,row_number() over (partition by t1.TDate, t1.TType order by t1.TDate) rn
from #TableX t1
) td
on(tt.TDate = td.TDate)
)
select r.TDate
,r.TType
,d.Fruit
,d.Vegetable
,d.Meat
,d.Bread
from DataRN d
full join RowsRN r
on(d.TDate = r.TDate
and d.TType = r.TType
and d.rn = r.rn
)
order by r.TDate
,r.TType
,isnull(d.Fruit,REPLICATE(CHAR(255),20))
,isnull(d.Vegetable,REPLICATE(CHAR(255),20))
,isnull(d.Meat,REPLICATE(CHAR(255),20))
,isnull(d.Bread,REPLICATE(CHAR(255),20))
In response to your comment, here is how you would use another cte to generate the full list of dates that you would need, if you havn't got a Dates reference table already (These are tremendously useful):
declare #MinDate date = (select min(TDate) from #TableX);
declare #MaxDate date = (select max(TDate) from #TableX);
with Dates as
(
select #MinDate as DateValue
union all
select dateadd(d,1,DateValue)
from Dates
where DateValue < #MaxDate
)
select DateValue
from Dates
option (maxrecursion 0);

Procedures with tables t-sql

I am testing one procedure with one table.
My procedure:
{
ALTER PROCEDURE [dbo].[CalculateAge]
AS
BEGIN
DECLARE #today datetime, #thisYearBirthDay datetime, #dayOfBirth datetime
DECLARE #years int, #months int, #days int Declare #y nvarchar(10), #m nvarchar(10), #d nvarchar(10)
Declare #sql nvarchar(max)
DECLARE #b varchar(100)
SET #dayOfBirth = ( SELECT top 1 birth from emp)
SELECT #today = GETDATE()
SELECT #thisYearBirthDay = DATEADD(year, DATEDIFF(year, #dayOfBirth, #today), #dayOfBirth)
SELECT #years = DATEDIFF(year, #dayOfBirth, #today) - (CASE WHEN #thisYearBirthDay > #today THEN 1 ELSE 0 END)
SELECT #months = MONTH(#today - #thisYearBirthDay) - 1
SELECT #days = DAY(#today - #thisYearBirthDay) - 1
SET #b = cast(#dayOfBirth as varchar(100))
SET #y = cast(#years as nvarchar(10))
SET #m = cast(#months as nvarchar(10))
SET #d = cast(#days as nvarchar(10))
SET #sql = N'select Name, birth, '+#y+' as [Metai], '+#m+' as [Menuo], '+#d+' as [Diena] from emp'
exec sp_executesql #sql
end
}
And my table info from emp:
1 BASAVARAJ BIRADAR 1985-04-11 00:00:00.000 NULL NULL NULL
2 SHREE BIRADAR 2013-01-25 00:00:00.000 NULL NULL NULL
After execute this procedure Exec CalculateAge I got:
BASAVARAJ BIRADAR 1985-04-11 00:00:00.000 28 9 18
SHREE BIRADAR 2013-01-25 00:00:00.000 28 9 18
SET #dayOfBirth = ( SELECT top 1 birth from emp)
I can use only one value, if I remove "top 1" I get error
How to make it that I should this result after procedure Exec CalculateAge :
BASAVARAJ BIRADAR 1985-04-11 00:00:00.000 28 9 18
SHREE BIRADAR 2013-01-25 00:00:00.000 1 0 2
I want to calculate every birth colummn from emp table with this procedure for two way:
Only execute this procedure
Insert EXEC procedure restuls into table emp into new columm a, b, c of each rows
You're not going to be able to use a variable (i.e., #dayofbirth) to calculate age for each employee using a query that selects only the Top 1 birthdate. This is because your variable requires a single value for the entire procedure, while you want a single birthdate value for each employee, which is not specified in your current select statement. To make this work, you would have to pass a value into your procedure, such as an employee ID, that would bring back just the employee's birthdate for the desired employee.
Now, you may have a good reason for using a stored procedure to calculate age, but there are simpler ways to calculate age. The calculation below took 1.4 seconds to calculate age for 150,000 rows, which includes delays for network traffic and such. Also, it is an exact way of calculating someone's age in years as of the current system time. We use this calculation on all of our systems, including Dashboards which require very quick response time for end-users.
Select ID
, (DATEDIFF(YY, DOB.BIRTHDATE, GETDATE()) -
Case
When( (MONTH(DOB.BIRTHDATE)*100
+ DAY(DOB.BIRTHDATE)) > (MONTH(GETDATE())*100
+ DAY(GETDATE())) )
Then 1
Else 0
End) as Age

spltting the row data with cursor and insert data into different columns

Hi I have string like
'spla - asqlserver 2008 #P1 Q TY 1
:SPLA-WINSV QWSRSTDA#P29- 9 QTY2:SP
LA-WINSVMSTDA #P29-999QTY2:SPLA-WINSVRSTD-sqlserver 2008#P 9 9 9 QT Y3:SPLA-WINSVRSTD #P
9-999QTY4 : SPLA-WINSVRSvr3# 59-99 Q TY5:SP -WI Sa 1 #P 999 Q T Y6'
and I wrote function like
ALTER function [dbo].[string_splitting_WORKING]
(
#STR VARCHAR(MAX),
#DELIMITER CHAR(1)
)
RETURNS #Result Table
(
Output varchar(max)
)
as
begin
DECLARE #Index int
declare #Output varchar(max)
select #index = 1
IF #STR IS NULL RETURN
WHILE #Index ! = 0
BEGIN
SELECT #Index = CHARINDEX(#Delimiter, #Str)
IF #Index != 0
SELECT #Output = LEFT(#Str, #Index - 1)
--ltrim(ltrim(substring(#Str,0,charindex('#',#Str))))
--LEFT(#Str, #Index - 1)
ELSE
SELECT #Output = #Str
INSERT INTO #Result(Output) VALUES (#Output)
SELECT #Str = RIGHT(#Str, LEN(#Str) - #Index)
IF LEN(#Str) = 0
BREAK
END
RETURN
END;
when u pass the string into the function like this
select * from [dbo].[string_splitting_WORKING]('SAQa # P 1 9 s-9 9 9 9 1:SPLA-WINSVRSTDA#P29-999QTY2
:SPLA-WINS VMSTDA#P 29-99 9Q TY2:SPLA-WggaerINSVRSTD# P3 9-9 99 9 Q TY3:SPLA-WINSVRSTD#P49-9999QTY4:SPLA-WINSVRSvr3#P59-9999QTY5:SPLA-WINSVRSat1#P69-9999QTY6 :',':')
I am getting output like this
SAQa # P 1 9 s-9 9 9 9 1
SPLA-WINSVRSTDA#P29-999QTY2
SPLA-WINS VMSTDA#P 29-99 9Q TY2
SPLA-WggaerINSVRSTD# P3 9-9 99 9 Q TY3
SPLA-WINSVRSTD#P49-9999QTY4
SPLA-WINSVRSvr3#P59-9999QTY5
SPLA-WINSVRSat1#P69-9999QTY6
I wrote another function
ALTER FUNCTION [dbo].[RowStringSplit]
(
#RowData varchar(8000),
#Delimiter varchar(5)
)
RETURNS #RtnValue table
( ServerName varchar(1000),
PoNumber varchar(500),
Qty varchar(100))
AS
BEGIN
Declare #Cnt int
Set #Cnt = 1
While (Charindex(#Delimiter,#RowData)>0)
Begin
Insert Into #RtnValue (Servername,PoNumber)--,Qty)
Select ServerName = ltrim(ltrim(Substring(#RowData,0,Charindex('#',#RowData)))),
--PoNumber = ltrim(ltrim(substring(#RowData,charindex('#',#RowData)+1,CHARINDEX(':',#RowData)-1))) --1
--PoNumber = substring(#RowData,charindex('#',#RowData)+1,len(#RowData)) --2
PoNumber = substring(#RowData,charindex('#',#RowData)+1,charindex('QTY',REVERSE(#RowData))+ #Cnt)--3
--PoNumber = case charindex('#',#RowData),1) when 0 then #RowData
-- else
-- substring(#RowData,1,charindex('QTY',#RowData,1)-1
--Qty = substring(#RowData,charindex('QTY',#RowData),Charindex(':',#RowData)-26)
Set #RowData = Substring(#RowData,Charindex(#Delimiter,#RowData)+1,len(#RowData))
Set #Cnt = #Cnt + 1
End
Insert Into #RtnValue (ServerName)
Select Data = ltrim(rtrim(#RowData))
Return
END
and I am getting output like this
ServerName PoNumber Qty
------------------------------------------------
spla - asqlserver 2008 P NULL
SPLA-WINSV QWSRSTDA P2 NULL
SP LA-WINSVMSTDA P29 NULL
SPLA-WINSVRSTD-sqlserver 2008 P 9 NULL
SPLA-WINSVRSTD P 9 NULL
SPLA-WINSVRSvr3 59-99 NULL
SP -WI Sa 1 P 99 NULL
but the requirement is if i remove the data from serverName column It has to show blank and If
I increase the data in the serverName column It should increase but I am getting that
but the problem is if I remove or add the data after # until qty that is from p upto qty the reset Its not comming exactly and last I need only number in the qty column
will u help me how to get the proper output by using function or procedure to split that string
from anand
Please try this. Looks like it's returning the correct output for your input string.
CREATE FUNCTION test (#a VARCHAR(1000))
RETURNS #RtnValue table (
ServerName varchar(1000),
PoNumber varchar(500),
Qty varchar(100)
)
AS
BEGIN
DECLARE #part1 VARCHAR(1000)
DECLARE #part2 VARCHAR(1000)
DECLARE #part3 VARCHAR(1000)
DECLARE #i INT
SELECT #a = LTRIM(RTRIM(#a))
SELECT #i = PATINDEX('%#%', #a)
IF #i = 0 SELECT #i = LEN(#a)
SELECT #part1 = LEFT(#a, #i - 1)
SELECT #a = RIGHT(#a, LEN(#a) - #i)
SELECT #a = REPLACE(#a, ' ', '')
SELECT #i = PATINDEX('%QTY%', #a)
IF #i > 0
BEGIN
SELECT #part2 = LEFT(#a, #i - 1)
SELECT #part3 = RIGHT(#a, LEN(#a) - LEN(#part2) - 3)
END
ELSE
SELECT #part2 = #a
INSERT #RtnValue
SELECT #part1, #part2, #part3
RETURN
END
GO
Execute it together with your function named string_splitting_WORKING:
select t.*
from [dbo].[string_splitting_WORKING]('spla - asqlserver 2008 #P1 Q TY 1
:SPLA-WINSV QWSRSTDA#P29- 9 QTY2:SP
LA-WINSVMSTDA #P29-999QTY2:SPLA-WINSVRSTD-sqlserver 2008#P 9 9 9 QT Y3:SPLA-WINSVRSTD #P
9-999QTY4 : SPLA-WINSVRSvr3# 59-99 Q TY5:SP -WI Sa 1 #P 999 Q T Y6'
,':')
CROSS APPLY dbo.test([Output]) t
It outputs:
ServerName PoNumber Qty
------------------------------------------------
spla - asqlserver 2008 P1 1
SPLA-WINSV QWSRSTDA P29-9 2
SP LA-WINSVMSTDA P29-999 2
SPLA-WINSVRSTD-sqlserver 2008 P999 3
SPLA-WINSVRSTD P 9-999 4
SPLA-WINSVRSvr3 59-99 5
SP -WI Sa 1 P999 6

Implementing and applying a string split in T-SQL

I have this statement in T-SQL.
SELECT Bay From TABLE where uid in (
select B_Numbers from Info_Step WHERE uid = 'number'
)
I am selecting "multiple" BAYs from TABLE where their uid is equal to a string of numbers like this:
B_Numbers = 1:45:34:98
Therefore, I should be selecting 4 different BAYs from TABLE. I basically need to split the string 1:45:34:98 up into 4 different numbers.
I'm thinking that Split() would work, but it doesn't and I get a syntax error.
Any thoughts from the T-SQL gods would be awesome!
Here is an implementation of a split function that returns the list of numbers as a table:
http://rbgupta.blogspot.com/2007/03/split-function-tsql.html
Looks like this would set you on your way...
Here is a method that uses an auxiliary numbers table to parse the input string. The logic can easily be added to a function that returns a table. That table can then be joined to lookup the correct rows.
Step 1: Create the Numbers table
SET NOCOUNT ON
GO
IF EXISTS
(
SELECT 1
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'Numbers'
AND TABLE_SCHEMA = 'dbo'
AND TABLE_TYPE = 'BASE TABLE'
)
BEGIN
DROP TABLE dbo.Numbers
END
GO
CREATE TABLE dbo.Numbers
(
Number smallint IDENTITY(1, 1) PRIMARY KEY
)
GO
WHILE 1 = 1
BEGIN
INSERT INTO dbo.Numbers DEFAULT VALUES
IF SCOPE_IDENTITY() = 32767
BEGIN
BREAK
END
END
GO
Step 2: Parse the Input String
CREATE FUNCTION dbo.ParseString(#input_string varchar(8000), #delim varchar(8000) = " ")
RETURNS TABLE
AS RETURN
(
SELECT Number
FROM dbo.Numbers
WHERE CHARINDEX
(
#delim + CONVERT(VARCHAR(12),Number) + #delim,
#delim + #input_string + #delim
) > 0
)
GO
**EXAMPLE**
SELECT * FROM dbo.ParseString('1:45:34:98',':')
Step 3: Use the results however you want/need
Number
------
1
34
45
98
End-To-End Example
Create function that returns the appropriate BNumber (of course change it to use the commented out SQL)
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION dbo.GetBNumber (#uid int)
RETURNS VARCHAR(8000)
AS
BEGIN
RETURN '1:45:34:98'
--select B_Numbers from Info_Step WHERE uid = #uid
END
GO
Use the use functions to return the desired results
-- Using Test Data
SELECT N.Number FROM Numbers N
JOIN dbo.ParseString(dbo.GetBNumber(12345),':') Q ON Q.Number = N.Number
-- Using Your Data (Untested but should work.)
SELECT N.Bay
FROM TABLE N
JOIN dbo.ParseString(dbo.GetBNumber(ENTER YOU NUMBER HERE),':') Q ON Q.Number = N.uid
Results
Number
------
1
34
45
98
You should keep your arrays as rows but if I understand your question I think this will work.
SELECT
Bay
From
TABLE
join Info_Step
on B_Numbers like '%'+ uid +'%'
where
Info_Step.uid = 'number'
This query will do a full table scan because of the like operator.
What you can do is loop through the B_Numbers entries and do your own split on : Insert those entries into a temp table and then perform your query.
DECLARE #i int
DECLARE #start int
DECLARE #B_Numbers nvarchar(20)
DECLARE #temp table (
number nvarchar(10)
)
-- SELECT B_Numbers FROM Info_Step WHERE uid = 'number'
SELECT #B_Numbers = '1:45:34:98'
SET #i = 0
SET #start = 0
-- Parse out characters delimited by ":";
-- Would make a nice user defined function.
WHILE #i < len(#B_Numbers)
BEGIN
IF substring(#B_Numbers, #i, 1) = ':'
BEGIN
INSERT INTO #temp
VALUES (substring(#B_Numbers, #start, #i - #start))
SET #start = #i + 1
END
SET #i = #i + 1
END
-- Insert last item
INSERT INTO #temp
VALUES (substring(#B_Numbers, #start, #i - #start + 1))
-- Do query with parsed values
SELECT Bay FROM TABLE WHERE uid in (SELECT * FROM #temp)
You can even try this
declare #str varchar(50)
set #str = '1:45:34:98'
;with numcte as(
select 1 as rn union all select rn+1 from numcte where rn<LEN(#str)),
getchars as(select
ROW_NUMBER() over(order by rn) slno,
rn,chars from numcte
cross apply(select SUBSTRING(#str,rn,1) chars)X where chars = ':')
select top 1
Bay1 = SUBSTRING(#str,0,(select rn from getchars where slno = 1))
,Bay2 = SUBSTRING(#str,
(select rn from getchars where slno = 1) + 1,
(((select rn from getchars where slno = 2)-
(select rn from getchars where slno = 1)
)-1))
,Bay3 = SUBSTRING(#str,
(select rn from getchars where slno = 2) + 1,
(((select rn from getchars where slno = 3)-
(select rn from getchars where slno = 2)
)-1))
,Bay4 = SUBSTRING(#str,
(select rn from getchars where slno = 3)+1,
LEN(#str))
from getchars
Output:
Bay1 Bay2 Bay3 Bay4
1 45 34 98