0

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!

5 Answers 5

2

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...

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

Comments

2

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

Comments

0

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.

1 Comment

This will not work because the input string needs to be separated into tokens (4 different rows) and then the tables joined together. Your method will try and find an UID like '.....1:45:34:98.....', which is not the case as UID is probably an integer.
0

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)

Comments

0

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

Comments

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.