tags:

views:

935

answers:

6

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!

A: 

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.

jms
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.
beach
+2  A: 

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

ScottStonehouse
A: 

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)
Gavin Miller
+1  A: 

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
beach
A: 

Good grief... what's with all the loops here? Someone even used a loop to build the Numbers table. What kind of an example are you setting with something like that?

--Jeff Moden

Jeff Moden
A: 

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