|
|
|
SSC-Dedicated
           
Group: General Forum Members
Last Login: Today @ 3:58 PM
Points: 32,899,
Visits: 26,780
|
|
romah (3/14/2013)
I found in other forums that "cross apply" only works if the compatibility_level is greater than 80. When I checked the compatibility_level of our database, it's 80. SELECT compatibility_level FROM sys.databases WHERE name = 'database_name'
I think Eugene's solution works in greater compatibility-level but I don't have permission to change it. Thanks once again Eugene ! 
NP. I am, however, concerned that Eugene is correct about the future. Please post your fnSplit function (ironically named) and lets see if we can make this code a bit more bullte proof for the future scalability..
--Jeff Moden "RBAR is pronounced "ree-bar" and is a "Modenism" for "Row-By-Agonizing-Row".
First step towards the paradigm shift of writing Set Based code: Stop thinking about what you want to do to a row... think, instead, of what you want to do to a column."
For better, quicker answers on T-SQL questions, click on the following... http://www.sqlservercentral.com/articles/Best+Practices/61537/
For better answers on performance questions, click on the following... http://www.sqlservercentral.com/articles/SQLServerCentral/66909/
|
|
|
|
|
Grasshopper
      
Group: General Forum Members
Last Login: Saturday, March 16, 2013 9:50 PM
Points: 18,
Visits: 66
|
|
Yes, Eugene's solution worked with compatibility_level=100 when I tested in my local machine.
select D.Item as [Category], COUNT(*) AS Count from dbo.TestCategory as T cross apply ( select * from dbo.fnSplit(T.[Category],'/') ) as D group by D.Item
As Eugene's earlier reply, I copied the DelimitedSplit8K() function from Jeff Moden's (your) article http://www.sqlservercentral.com/articles/Tally+Table/72993/ and renamed as fnSplit() in my database. 
ALTER FUNCTION dbo.fnSplit --===== 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 ;
Once again Thank you all for helping me
|
|
|
|