sql server 2008 dynamic pivot based on ordinal val

2019-05-26 03:22发布

问题:

I have a UDF that splits a character string delimited by a space. As the function loops through each string if it finds a space and makes a split an ordinal number is inserted into the results table in its own column along with the split string. I have pivoted on this ordinal number but of course these numbers change based on the character string. I need to query these ordinal numbers and use them in my pivot. Could someone show me how this could be done with dynamic sql? I have seen examples on different forums but I think this could be more simple than what I've seen. My proceedure is below. If someone needs the UDF I'll post it as well.

--The original data is pulled from column "DataString" in "MyData" table.
--After declaring the UDF split function the function is used and the results are
--inserted into a table called "ScriptResult" with this query
SELECT * 
INTO ScriptResult
FROM    
    MyData x    
    CROSS APPLY    
    dbo.Split (x.DataString, ' ') S

Where rtrim(s.StringValue) != '' 

--Then the table is pivoted on column Ordinal from table ScriptResult to summarize the data

Select *
INTO ScriptPivot
From ScriptResult
pivot (max (StringValue) for Ordinal in ([1], [2], [3], [5], [7], [8], [9], [10], [11]))
as   PivotResult 

Example Input:

R 456 ACCOUNT 56779900 23499000800973983989883 56 99750927     890-0983
Y 123M 120 M/Y JOHN DOE E 5678873940000056 000000 0003456      678-7898
U 06           000000 000567 000000000000000000M688399000      789-8388
H 120                                                          785-7848
R 456          0000000000000000000006578 786936689663   DTY578   568-7890

I'm taking an old flat file and de-enginering it into sql. The problem is the batch process that creates these files just has 120 character rows with no normalization etc. I'm trying to get them into Sql Server. I relize i could do this easier with an import wizard but I need a Stor.Proceedure because these flats are still being used and this will have to be done on a daily basis. Desired Result: The pivot table I have is the result I need but I just need to be able to use this for all data strings I get like this and none of them are uniform so the ordinal numbers differ. But this is how it should look...

1---2---3-------5--------7----------8-------------9--10-----------11   
R   456 ACCOUNT 56779900 2349900080 0973983989883 56 99750927     890-0983

Here is an example dynamic pivot table from the adventure works DB... DECLARE @PivotColumnHeaders VARCHAR(MAX) SELECT @PivotColumnHeaders = COALESCE( @PivotColumnHeaders + ',[' + cast(Name as varchar) + ']', '[' + cast(Name as varchar)+ ']' ) FROM Sales.SalesTerritory

DECLARE @PivotTableSQL NVARCHAR(MAX)
SET @PivotTableSQL = N'
  SELECT *
  FROM (
    SELECT
      YEAR(H.OrderDate) [Year],
      T.Name,
      H.TotalDue
    FROM Sales.SalesOrderHeader H
    LEFT JOIN Sales.SalesTerritory T
      ON H.TerritoryID = T.TerritoryID
  ) AS PivotData
  PIVOT (
    SUM(TotalDue)
    FOR Name IN (
      ' + @PivotColumnHeaders + '
    )
  ) AS PivotTable
'

EXECUTE(@PivotTableSQL)

Could I somehow tailor this for my use?

回答1:

If you were to have a table called Ordinals (or whatever you want) that contains numbers sufficient to cover the maximum number of ordinals you might attain, this may work for you:-

declare @ordList varchar(max);
select @ordList = stuff((select ', [' + rtrim(ordinal) + ']' as [text()] 
from ( 
    select distinct convert(varchar,ordinal) ordinal from Ordinals 
) ords for xml path('')),1,1,'')

exec ('select * from ( select ' + @ordList + ' from dataTable) tbl pivot (max(stringValue) FOR [1] in (' + @ordList + ')) PVT' ) end

This is pretty much the same as the AW sample