7

I have a stored procedure

SELECT [ShipWorks].[dbo].[OrderItem].[Code] AS Code, 
 CASE WHEN (LEN(ISNULL(MAX([ShipWorks].[dbo].[OrderItem].[Location]),'')) = 1)
 THEN MAX([ShipWorks].[dbo].[OrderItem].[Location]) 
 ELSE MAX([Picklist].[dbo].[ItemData].[InventoryLocation])
 END AS Location, 
SUM([ShipWorks].[dbo].[OrderItem].[Quantity]) AS Quantity, 
MAX(LEFT([ShipWorks].[dbo].[Store].[StoreName], 1)) AS Store
FROM [ShipWorks].[dbo].[OrderItem] 
INNER JOIN [ShipWorks].[dbo].[Order] ON [ShipWorks].[dbo].[OrderItem].[OrderID] = [ShipWorks].[dbo].[Order].[OrderID] 
INNER JOIN [ShipWorks].[dbo].[Store] ON [ShipWorks].[dbo].[Order].[StoreID] = [ShipWorks].[dbo].[Store].[StoreID] 
LEFT JOIN [ShipWorks].[dbo].[AmazonOrder] ON [ShipWorks].[dbo].[AmazonOrder].[OrderID] = [ShipWorks].[dbo].[Order].[OrderID]
LEFT JOIN [Picklist].[dbo].[ItemData] ON [Picklist].[dbo].[ItemData].[InventoryNumber] = [ShipWorks].[dbo].[OrderItem].[Code] OR
 [Picklist].[dbo].[ItemData].[MediaCreator] = [OrderItem].[Code]
WHERE [ShipWorks].[dbo] [Order].[LocalStatus] = 'Recently Downloaded' AND ([ShipWorks].[dbo].[AmazonOrder].[FulfillmentChannel] = 2 OR [ShipWorks].[dbo].[Store].[StoreName] <> 'Amazon')
GROUP BY [ShipWorks].[dbo].[OrderItem].[Code]
ORDER BY Location

that returns this:

Code Location Quantity Store
L698-W-EA NULL 2 A
L82009-EA A1K2, A1N2, C4Y3, CBP2 2 A
L80401-A-EA A1S2, SHIP, R2F1, CBP5, BRP, BRP1-20 17 A
CWD2132W-BOX-25PK A-AISLE 1 M
GM22660003-EA B1K2 1 M

I want to split the Location column into multiple columns .

Code loc1 loc2 loc3 loc4 loc5 loc6 Quantity Store
L698-W-EA NULL 2 A
L82009-EA A1K2, A1N2, C4Y3, CBP2 2 A
L80401-A-EA A1S2, SHIP, R2F1, CBP5, BRP, BRP1-20 17 A
CWD2132W-BOX-25PK A-AI 1 M
GM22660003-EA B1K2 1 M

I found this answer but that was for postgresql. Also this, but it returns a table with multiple rows and you can select the top 1 but I want all the results and I'm not sure how to use the tvf Split(string, ',')in the stored procedure to get the result set I want?

This select statement results in a error: 'Cannot perform an aggregate function on an expression containing an aggregate or a subquery.'

SELECT [ShipWorks].[dbo].[OrderItem].[Code] AS Code, 
 CASE WHEN (LEN(ISNULL(MAX([ShipWorks].[dbo].[OrderItem].[Location]),'')) = 1)
 THEN MAX((SELECT TOP 1 i.* FROM dbo.Split([ShipWorks].[dbo].[OrderItem].[Location], ',') as i)) 
 ELSE MAX((SELECT TOP 1 i.* FROM dbo.Split([ShipWorks].[dbo].[OrderItem].[Location], ',') as i))
 END AS Location, 
SUM([ShipWorks].[dbo].[OrderItem].[Quantity]) AS Quantity, 
MAX(LEFT([ShipWorks].[dbo].[Store].[StoreName], 1)) AS Store
FROM [ShipWorks].[dbo].[OrderItem] 
INNER JOIN [ShipWorks].[dbo].[Order] ON [ShipWorks].[dbo].[OrderItem].[OrderID] = [ShipWorks].[dbo].[Order].[OrderID] 
INNER JOIN [ShipWorks].[dbo].[Store] ON [ShipWorks].[dbo].[Order].[StoreID] = [ShipWorks].[dbo].[Store].[StoreID] 
LEFT JOIN [ShipWorks].[dbo].[AmazonOrder] ON [ShipWorks].[dbo].[AmazonOrder].[OrderID] = [ShipWorks].[dbo].[Order].[OrderID]
LEFT JOIN [Picklist].[dbo].[ItemData] ON [Picklist].[dbo].[ItemData].[InventoryNumber] = [ShipWorks].[dbo].[OrderItem].[Code] OR
 [Picklist].[dbo].[ItemData].[MediaCreator] = [OrderItem].[Code]
WHERE [Order].[LocalStatus] = 'Recently Downloaded' AND ([ShipWorks].[dbo].[AmazonOrder].[FulfillmentChannel] = 2 OR [ShipWorks].[dbo].[Store].[StoreName] <> 'Amazon')
GROUP BY [ShipWorks].[dbo].[OrderItem].[Code]
ORDER BY Location
asked Jul 24, 2014 at 16:47

1 Answer 1

6

Making use of Jeff Moden's Tally-Ho! CSV splitter from here:

CREATE FUNCTION [dbo].[DelimitedSplit8K]
--===== Define I/O parameters
 (@pString VARCHAR(8000), @pDelimiter CHAR(1))
--WARNING!!! DO NOT USE MAX DATA-TYPES HERE! IT WILL KILL PERFORMANCE!
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
--===== "Inline" CTE Driven "Tally Table" produces values from 1 up to 10,000...
 -- enough to cover VARCHAR(8000)
WITH E1(N) AS (
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
 ), --10E+1 or 10 rows
 E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
 E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS (--==== This provides the "base" CTE and limits the number of rows right up front
 -- for both a performance gain and prevention of accidental "overruns"
 SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() 
 OVER (ORDER BY (SELECT NULL)) FROM E4
 ),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just
 -- once for each delimiter)
 SELECT 1 UNION ALL
 SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
 ),
cteLen(N1,L1) AS(--==== Return start and length (for use in substring)
 SELECT s.N1,
 ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000)
 FROM cteStart s
 )
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final
 -- element when no delimiter is found.
 SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
 Item = SUBSTRING(@pString, l.N1, l.L1)
 FROM cteLen l
;
go

We can code the solution as an apply against Jeff's function and a pivot like so:

with data as (
 select Code,Location,Quantity,Store from ( values
 ('L698-W-EA', NULL, 2, 'A')
 ,('L82009-EA', 'A1K2, A1N2, C4Y3, CBP2', 2, 'A')
 ,('L80401-A-EA', 'A1S2, SHIP, R2F1, CBP5, BRP, BRP1-20', 17,'A')
 ,('CWD2132W-BOX-25PK', 'A-AISLE', 1, 'M')
 ,('GM22660003-EA', 'B1K2', 1, 'M')
 )data(Code,Location,Quantity,Store)
)
,shredded as (
 select Code,Location,Quantity,Store,t.*
 from data
 cross apply [dbo].[DelimitedSplit8K](data.Location,',') as t
)
select 
 pvt.Code,pvt.Quantity,pvt.Store
 ,cast(isnull(pvt.[1],' ') as varchar(8)) as Loc1
 ,cast(isnull(pvt.[2],' ') as varchar(8)) as Loc2
 ,cast(isnull(pvt.[3],' ') as varchar(8)) as Loc3
 ,cast(isnull(pvt.[4],' ') as varchar(8)) as Loc4
 ,cast(isnull(pvt.[5],' ') as varchar(8)) as Loc5 
 ,cast(isnull(pvt.[6],' ') as varchar(8)) as Loc6
from shredded
pivot (max(Item) for ItemNumber in ([1],[2],[3],[4],[5],[6])) pvt;
;
go

yielding this:

Code Quantity Store Loc1 Loc2 Loc3 Loc4 Loc5 Loc6
----------------- ----------- ----- -------- -------- -------- -------- -------- --------
L698-W-EA 2 A 
L82009-EA 2 A A1K2 A1N2 C4Y3 CBP2 
L80401-A-EA 17 A A1S2 SHIP R2F1 CBP5 BRP BRP1-20
CWD2132W-BOX-25PK 1 M A-AISLE 
GM22660003-EA 1 M B1K2 
answered Jul 24, 2014 at 18:08
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.