Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Parse multi-column array in sql stored procedure using a pivot (numbers) table

Posted on 2007-11-13
6
Medium Priority
?
1,272 Views
Last Modified: 2008-01-09
In order to parse an array passed in as a parameter in a stored procedure I use a stored procedure ripped from here: http://vyaskn.tripod.com/passing_arrays_to_stored_procedures.htm
To be more precise, it is method 5:
SELECT o.OrderID, CustomerID, EmployeeID, OrderDate
      FROM dbo.Orders AS o
      JOIN
      (
            
            SELECT LTRIM(RTRIM(SUBSTRING(OrderID, number+1, CHARINDEX(',', OrderID, number+1)-number - 1))) AS OrderID
            FROM      
            (
                  SELECT ',' + @OrderList + ',' AS OrderID
            ) AS InnerQuery
            JOIN
            Numbers n
            ON
            n.Number < LEN(InnerQuery.OrderID)
            WHERE SUBSTRING(OrderID, number, 1) = ','
      ) as Derived
      ON o.OrderID = Derived.OrderID
I use this sp to insert records in a table and instead of one column per insert (row) I need to do more.
For example, my input string would be something like:
col1_val1,col2_val1,col3_val1,col1_val2,col2_val2,col3_val2,col1_val3,col2_val3,col3_val3 ....
However, I can't get my head around how to build this query. I have tried a cross join to multiple Numbers table but that generates a cartesian product (I cannot get a distinct-like result).
Is there any way around it?
Thanks
0
Comment
Question by:daniel_balla
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
6 Comments
 
LVL 6

Expert Comment

by:Rajesh_mj
ID: 20278914
Hi,
First create dbo.SplitOrderIDs specified in the method 6
 http://vyaskn.tripod.com/passing_arrays_to_stored_procedures.htm

Then just try this:

(I have used orderid,ShipVia,EmployeeID as three columns ).



declare @OrderList varchar(1000),@Col1 varchar(1000),@Col2 varchar(1000),@Col3 varchar(1000)
SET @OrderList ='10248,3,5,10259,3,4'


drop table #newtable

Select  IDENTITY(int, 1,1) AS ID_Num, OrderID INTO  #NewTable from dbo.SplitOrderIDs(@OrderList)
select * from #NewTable

Select @col1 = '',@col2 = '',@Col3 =''

select @Col1 =@Col1+cast(OrderID as varchar(10))+',' from #NewTable where Id_Num % 3 = 1
select @Col2 =@Col2+cast(OrderID as varchar(10))+',' from #NewTable where Id_Num % 3 = 2
select @Col3 =@Col3+cast(OrderID as varchar(10))+',' from #NewTable where Id_Num % 3 = 0

SELECT Distinct o.OrderID, CustomerID, EmployeeID, OrderDate
      FROM dbo.Orders AS o
      JOIN
      (
           
            SELECT LTRIM(RTRIM(SUBSTRING(Column1, number+1, CHARINDEX(',', Column1, number+1)-number - 1))) AS Column1
            FROM      
            (
                  SELECT ',' + @col1 + ',' AS Column1
            ) AS InnerQuery
            JOIN
            Numbers n
            ON
            n.Number < LEN(InnerQuery.Column1)
            WHERE SUBSTRING(Column1, number, 1) = ','

      ) as Derived1

      ON o.OrderID = Derived1.Column1

      JOIN
      (
           
            SELECT LTRIM(RTRIM(SUBSTRING(Column2, number+1, CHARINDEX(',', Column2, number+1)-number - 1))) AS Column2
            FROM      
            (
                  SELECT ',' + @col2 + ',' AS Column2
            ) AS InnerQuery
            JOIN
            Numbers n
            ON
            n.Number < LEN(InnerQuery.Column2)
            WHERE SUBSTRING(Column2, number, 1) = ','

      ) as Derived2

      ON o.ShipVia = Derived2.Column2
 JOIN
      (
           
            SELECT LTRIM(RTRIM(SUBSTRING(Column3, number+1, CHARINDEX(',', Column3, number+1)-number - 1))) AS Column3
            FROM      
            (
                  SELECT ',' + @col3 + ',' AS Column3
            ) AS InnerQuery
            JOIN
            Numbers n
            ON
            n.Number < LEN(InnerQuery.Column3)
            WHERE SUBSTRING(Column3, number, 1) = ','

      ) as Derived3

      ON o.EmployeeID = Derived3.Column3



0
 
LVL 9

Author Comment

by:daniel_balla
ID: 20284325
Fair enough, but as far as I can see the idea is to use the pivot table instead of the expensive string parsing (such as the specified UDF does) to optimize the whole process.
How is the proposed method any better than just parsing the string (using a while and the substring) and doing the inserts in the while loop?
do you reckon there is no way it can be done just using the join to the numbers table (so no loop around to parse the string)?
0
 
LVL 6

Accepted Solution

by:
Rajesh_mj earned 2000 total points
ID: 20287378
Hi,
Just try: (Hope that it is some thing more better)

Declare @OrderList varchar(1000)
SET @OrderList ='10248,3,5,10259,3,4'

SELECT Distinct o.OrderID, CustomerID, EmployeeID, OrderDate
      FROM dbo.Orders AS o
      JOIN
      (
           
            SELECT LTRIM(RTRIM(SUBSTRING(OrderID, number+1, CHARINDEX(',', OrderID, number+1)-number - 1))) AS OrderID,
(LEN(SUBSTRING(OrderID,1,number+1)) -
            LEN(REPLACE(SUBSTRING(OrderID,1,number+1), ',', ''))) /
            LEN(',') as Num

            FROM      
            (
                  SELECT ',' + @OrderList + ',' AS OrderID
            ) AS InnerQuery
            JOIN
            Numbers n
            ON
            n.Number < LEN(InnerQuery.OrderID)
            WHERE SUBSTRING(OrderID, number, 1) = ','
      ) as Derived
      ON o.OrderID = CASE WHEN Derived.Num % 3 = 1 THEN Derived.OrderID END
 JOIN
      (
           
            SELECT LTRIM(RTRIM(SUBSTRING(OrderID, number+1, CHARINDEX(',', OrderID, number+1)-number - 1))) AS OrderID,
(LEN(SUBSTRING(OrderID,1,number+1)) -
            LEN(REPLACE(SUBSTRING(OrderID,1,number+1), ',', ''))) /
            LEN(',') as Num

            FROM      
            (
                  SELECT ',' + @OrderList + ',' AS OrderID
            ) AS InnerQuery
            JOIN
            Numbers n
            ON
            n.Number < LEN(InnerQuery.OrderID)
            WHERE SUBSTRING(OrderID, number, 1) = ','
      ) as Derived1
      ON o.ShipVia = CASE WHEN Derived1.Num % 3 = 2 THEN Derived1.OrderID END
JOIN
      (
           
            SELECT LTRIM(RTRIM(SUBSTRING(OrderID, number+1, CHARINDEX(',', OrderID, number+1)-number - 1))) AS OrderID,
(LEN(SUBSTRING(OrderID,1,number+1)) -
            LEN(REPLACE(SUBSTRING(OrderID,1,number+1), ',', ''))) /
            LEN(',') as Num

            FROM      
            (
                  SELECT ',' + @OrderList + ',' AS OrderID
            ) AS InnerQuery
            JOIN
            Numbers n
            ON
            n.Number < LEN(InnerQuery.OrderID)
            WHERE SUBSTRING(OrderID, number, 1) = ','
      ) as Derived2
      ON o.EmployeeID = CASE WHEN Derived2.Num % 3 = 0 THEN Derived2.OrderID END
0
Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

 
LVL 6

Expert Comment

by:Rajesh_mj
ID: 20287390
Hi,
Using temp table:
Declare @OrderList varchar(1000)
SET @OrderList ='10248,3,5,10259,3,4'


            SELECT LTRIM(RTRIM(SUBSTRING(OrderID, number+1, CHARINDEX(',', OrderID, number+1)-number - 1))) AS OrderID,
(LEN(SUBSTRING(OrderID,1,number+1)) -
            LEN(REPLACE(SUBSTRING(OrderID,1,number+1), ',', ''))) /
            LEN(',') as Num
            INTO #tmp
            FROM      
            (
                  SELECT ',' + @OrderList + ',' AS OrderID
            ) AS InnerQuery
            JOIN
            Numbers n
            ON
            n.Number < LEN(InnerQuery.OrderID)
            WHERE SUBSTRING(OrderID, number, 1) = ','


SELECT Distinct o.OrderID, CustomerID, EmployeeID, OrderDate
      FROM dbo.Orders AS o
      JOIN
       #tmp as Derived
      ON o.OrderID = CASE WHEN Derived.Num % 3 = 1 THEN Derived.OrderID END
 JOIN
      #tmp as Derived1
      ON o.ShipVia = CASE WHEN Derived1.Num % 3 = 2 THEN Derived1.OrderID END
JOIN
     #tmp Derived2
      ON o.EmployeeID = CASE WHEN Derived2.Num % 3 = 0 THEN Derived2.OrderID END
0
 
LVL 6

Expert Comment

by:Rajesh_mj
ID: 20287401
Hi,
I have taken Count String Occurrence Function from
 http://www.sql-server-helper.com/functions/count-string.aspx
0
 
LVL 9

Author Comment

by:daniel_balla
ID: 20289935
Thanks Rajesh. This might be the magic I need. Let me give it a try.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Recently we ran in to an issue while running some SQL jobs where we were trying to process the cubes.  We got an error saying failure stating 'NT SERVICE\SQLSERVERAGENT does not have access to Analysis Services. So this is a way to automate that wit…
One of the most important things in an application is the query performance. This article intends to give you good tips to improve the performance of your queries.
Familiarize people with the process of retrieving data from SQL Server using an Access pass-thru query. Microsoft Access is a very powerful client/server development tool. One of the ways that you can retrieve data from a SQL Server is by using a pa…
Viewers will learn how to use the SELECT statement in SQL and will be exposed to the many uses the SELECT statement has.

636 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question