February 8, 2007 at 12:07 pm
I need help in joining 2 tables using a Split function
TableA
ID | Nodes | LT |
M1 | 1;2;3 | 4 |
M2 | 4;5;6 | 5 |
TableB
ID | Desc | Qty |
1 | Desc of 1 | 2 |
2 | Desc of 2 | 13 |
3 | Desc of 3 | 43 |
4 | Desc of 4 | 52 |
5 | Desc of 5 | 66 |
6 | Desc of 6 | 77 |
The output should be
TableAID | LT | TableBID | Desc | Qty |
M1 | 4 | 1 | Desc of 1 | 2 |
M1 | 4 | 2 | Desc of 2 | 13 |
M1 | 4 | 3 | Desc of 3 | 43 |
M2 | 5 | 4 | Desc of 4 | 52 |
M2 | 5 | 5 | Desc of 5 | 66 |
M2 | 5 | 6 | Desc of 6 | 77 |
The Split Function takes in parameters of string of integers (Nodes column) and a delimiter and returns a table with elements. The elements of the split function joins to ID column of TableB.
Thanks
February 8, 2007 at 2:01 pm
You can use PATINDEX or CHARINDEX to get all the values from Nodes in Table A.
February 8, 2007 at 2:16 pm
Using Charindex and Substring functions will return just a single value. The split function returns a table
If I do a Split function as select * from dbo.split('4;5;6',';') I get back 3 rows as
ID Value
1 4
2 5
3 6
February 8, 2007 at 2:29 pm
eek I'm gonna say the words " only a cursor can solve this"; while I know cursor is the antithesis to all things SSC, sometimes you have to use the devil's tool:
create the expected table, and in the cursor insert them into the table:
create table #RESULTS (TableAID varchar(30), @Node varchar(100), @Qty int)
declare
@TableAID varchar(30),
@Nodes varchar(8000),
@Qty int
declare c1 cursor for select TableAID,Nodes,LT from TABLEA
open c1
fetch next from c1 into @TableAID,@Nodes,@Qty
While @@fetch_status <> -1
INSERT INTO #RESULTS SELECT @TABLEAID,@LT,Element from dbo.split(@NODES)
fetch next from c1 into @TableAID,@Nodes,@Qty
end
close c1
deallocate c1
Lowell
February 9, 2007 at 2:18 am
Cursor? Do you want your mouth washed out with soap?
All you need is:
Select A.ID As TableAID, A.LT, B.ID As TableBID, B.[Desc], B.Qty
From
TableA A
Inner
Join TableB B On B.ID IN (Select ParsedValue From dbo.FN_SplitString(A.Nodes, ';'))
My test code:
Create
Table TableA (ID varchar(2), Nodes varchar(5), LT int)
Create
Table TableB (ID int, [Desc] varchar(20), Qty int)
Insert
Into TableA Values ('M1', '1;2;3', 4)
Insert
Into TableA Values ('M2', '4;5;6', 5)
Insert
Into TableB Values (1, 'Desc of 1', 2)
Insert
Into TableB Values (2, 'Desc of 2', 13)
Insert
Into TableB Values (3, 'Desc of 3', 43)
Insert
Into TableB Values (4, 'Desc of 4', 52)
Insert
Into TableB Values (5, 'Desc of 5', 66)
Insert
Into TableB Values (6, 'Desc of 6', 77)
Select
A.ID As TableAID, A.LT, B.ID As TableBID, B.[Desc], B.Qty
From
TableA A
Inner
Join TableB B On B.ID IN (Select ParsedValue From dbo.FN_SplitString(A.Nodes, ';'))
Drop
Table TableA
Drop
Table TableB
February 9, 2007 at 4:29 am
* EDIT * Just noticed the original poster has a split function! so I guess you can ignore the next paragraph!
All good and well Robert, and am in agreement with you, apart from the fact that as far as I know fn_SplitString is not either a SQL 2000 nor 2005 system function, and therefore you would have to add this as well - and to do that you need create privelages for functions (this function and several like it are documented by several people so will not add it here).
February 9, 2007 at 4:37 am
curses on cursors! I am appropriately humbled. Thanks for putting me back on the path of enlightenment, Robert; I just couldn't "see" the subselect; nice solution.
Lowell
February 9, 2007 at 6:19 am
I also looked at the split function. It is not supported by Sql server 2000 and it was written using CHARINDEX.
I don't like the idea that using something that is not supported by SQL Server 2000 because when other people did not know where you got the function.
It is very easy to write the split function yourself using CHARINDEX in your procedure. This way it is clear to all the other developers.
my 2 cents.
February 9, 2007 at 7:21 am
function not supported by sql 2000....so you'll write your own function...um...that is also not supported?
I think you mean simply not explicitly written by microsoft...technically all stored procs, functions, views, or even table schema would fit that description. That's not a bad thing, they just give us the tools to get us started. We build what we need based off of business rules.
The split function works great for resolving situations where data was stuffed into a field instead of being normalized
don't reinvent the wheel and re-write your own split function; just take one of the fine functions off of SSC and add a nice descriptive header in it prior to putting it on your server; that way if people view the source, they'll have a good understanding of it's purpose and function.
Lowell
February 9, 2007 at 9:18 am
I have no idea what you are trying to say. There is no possible way that you looked at my split function that I wrote and is not publicly distributed.
Yes, the split function I wrote was very easy to write. It took me about 3 minutes. BUT there is nothing in my split function not supported by SQL 2000. Please explain what you mean by "not supported by SQL 2000".
He is already using his own split function, which is why I used a split function. Why would you suggest that he write his own split function when he has already done so?
February 9, 2007 at 1:09 pm
Thanks for you inputs.
Here is the Split Function that I wrote from one of the scripts on the site (not sure whom I need to give credit)
CREATE FUNCTION dbo.SplitToInt (@vcDelimitedString varchar(8000),
@vcDelimiter varchar(1) )
RETURNS @tblArray TABLE
(
ElementID smallint IDENTITY(1,1), --Array index
Element int --Array element contents
)
AS
BEGIN
DECLARE
@siIndex smallint,
@siStart smallint,
@siDelSize smallint
SET @siDelSize = LEN(@vcDelimiter)
--loop through source string and add elements to destination table array
WHILE LEN(@vcDelimitedString) > 0
BEGIN
SET @siIndex = CHARINDEX(@vcDelimiter, @vcDelimitedString)
IF @siIndex = 0
BEGIN
INSERT INTO @tblArray VALUES(CONVERT(int,@vcDelimitedString))
BREAK
END
ELSE
BEGIN
INSERT INTO @tblArray VALUES(CONVERT(int,SUBSTRING(@vcDelimitedString, 1,@siIndex - 1)))
SET @siStart = @siIndex + @siDelSize
SET @vcDelimitedString = SUBSTRING(@vcDelimitedString, @siStart , LEN(@vcDelimitedString) - @siStart + 1)
END
END
RETURN
END
But I still get a Incorrect Syntax near '.' error when I run the query by Robert Davis.
Select A.ID As TableAID, A.LT, B.ID As TableBID, B.[Desc], B.Qty
From TableA A
Inner Join TableB B On B.ID IN
(Select Element From dbo.SplitToInt(A.Nodes, ';'))
February 9, 2007 at 1:46 pm
There is no syntax error in the code I posted. Double check to make sure you didn't type something wrong.
If you don't see anything, please post the actual code you are using.
February 9, 2007 at 2:03 pm
Here is the complete script using the split function that I had put earlier.
Create Table TableA (ID varchar(2), Nodes varchar(5), LT int)
Create Table TableB (ID int, [Desc] varchar(20), Qty int)
Insert Into TableA Values ('M1', '1;2;3', 4)
Insert Into TableA Values ('M2', '4;5;6', 5)
Insert Into TableB Values (1, 'Desc of 1', 2)
Insert Into TableB Values (2, 'Desc of 2', 13)
Insert Into TableB Values (3, 'Desc of 3', 43)
Insert Into TableB Values (4, 'Desc of 4', 52)
Insert Into TableB Values (5, 'Desc of 5', 66)
Insert Into TableB Values (6, 'Desc of 6', 77)
Select A.ID As TableAID, A.LT, B.ID As TableBID, B.[Desc], B.Qty
From TableA A
Inner Join TableB B On B.ID IN
(Select Element From dbo.SplitToInt(A.Nodes, ';'))
February 9, 2007 at 2:18 pm
I get no errors running that code.
February 9, 2007 at 2:37 pm
Interesting. I still get this error
Server: Msg 170, Level 15, State 1, Line 29
Line 29: Incorrect syntax near '.'.
Could it due to some sort of settings in Query Analyzer ?
I ran this in both SQL 2000 and SQL 2005.
Viewing 15 posts - 1 through 15 (of 25 total)
You must be logged in to reply to this topic. Login to reply