2016-08-16 1 views
1

J'ai une table qui contient une collection de champs dans une seule colonne, j'essaie de la construire pour une vue correcte de chaque champ dans sa propre rangée, comme le suivant exemple:T-SQL Plusieurs auto-jointures dans une boucle

T_data: 
    +------+---------+---------+ 
    | ID | Field | Value | 
    +------+---------+---------+ 
    | 1 | Name | John | 
    | 1 | Age  | 41  | 
    | 1 | Height | 181  | 
    | 2 | Name | Kelly | 
    | 2 | Age  | 42  | 
    | 2 | Height | 165  | 
    | 3 | Name | Dan  | 
    | 3 | Age  | 43  | 
    | 3 | Height | 169  | 
    +------+---------+---------+ 

T_result: 
    +--------+--------+--------+--------+ 
    | Name | John | Kelly | Dan | 
    | Age | 41  | 42  | 43  | 
    | Height | 181 | 165 | 169 | 
    +--------+--------+--------+--------+ 

Je sais comment faire cela dans l'exemple avec trois auto-jointures sur la même table, mais cela est juste un exemple simplifié, mes données auront un nombre inconnu des ID et des champs - J'ai besoin de les parcourir d'une façon ou d'une autre et de les rejoindre dans une table dynamique. Comment pourrais-je atteindre mon résultat?

Ce genre est-ce que j'ai à l'esprit (ne fonctionne pas):

with #T_id as (
    select distinct ID, row_number() over (order by ID asc) as rn form T_data) 

    -- here's where I need to loop through the IDs 
    -- Pseudo-code ... I know the following doesn't work 

    while @i <= (select count(*) from #T_id) 
    begin 
    select T_data.Field, T_data.Value from T_data 
    left join T_result on T_data.Field = T_result.Field 
    where T_data.ID = (select ID from #T_id where rn = @i) 
    end 

Edit: Le résultat final est destiné à une procédure stockée à utiliser par le Reports Server.

Toute aide sera appréciée :)

+1

Google 'pivot dynamique dans le serveur SQL. Cela devrait vous aider à démarrer. – dfundako

+0

il semble que vous essayez de générer du SQL pour lire un nombre illimité d'attributs à partir de tables - voulez-vous utiliser SQL pour générer ce SQL (vous pouvez générer du SQL en SQL, puis exécuter le SQL), ou allez-vous générer la commande SQL dans un langage de programmation? Une autre approche consiste à créer une boucle ou un curseur qui lit les données, les insère dans une table temporaire, puis interroge finalement la table temporaire. Ou cherchez-vous une table PIVOT, ce qui semblerait mieux si vous pouviez le faire – Cato

Répondre

1

PIVOT est grande, mais j'utiliser une procédure stockée pour Dynamic Pivots

Exec [prc-Pivot] 'YourTable','ID','max(Value)[]','Field','count(*)[Records]' 

Retours

Field Records 1  2  3 
Age  3  41 42  43 
Height 3  181 165  169 
Name 3  John Kelly Dan 

La procédure stockée

CREATE PROCEDURE [dbo].[prc-Pivot] (
    @Source varchar(1000),   -- Any Table or Select Statement 
    @PvotCol varchar(250),   -- Field name or expression ie. Month(Date) 
    @Summaries varchar(250),  -- aggfunction(aggValue)[optionalTitle] 
    @GroupBy varchar(250),   -- Optional additional Group By 
    @OtherCols varchar(500))  -- Optional Group By or aggregates 
AS 

--Exec [prc-Pivot] 'Select Year=Year(TR_Date),* From [Chinrus-Series].[dbo].[DS_Treasury_Rates]','''Q''+DateName(QQ,TR_Date)','avg(TR_Y10)[-Avg]','Year','count(*)[Records],min(TR_Y10)[Min],max(TR_Y10)[Max],Avg(TR_Y10)[Avg]' 
--Exec [prc-Pivot] '#Temp','Attribute','max(Description)[]','ID','count(*)[Records]' 

Set NoCount On 
Set Ansi_Warnings Off 

Declare @Vals varchar(max),@SQL varchar(max); 
Set @Vals = '' 
Set @OtherCols= IsNull(', ' + @OtherCols,'') 
Set @Source = case when @Source Like 'Select%' then @Source else 'Select * From '[email protected] end 
Create Table #TempPvot (Pvot varchar(100)) 
Insert Into #TempPvot 
Exec ('Select Distinct Convert(varchar(100),' + @PvotCol + ') as Pvot FROM (' + @Source + ') A') 
Select @Vals = @Vals + ', isnull(' + Replace(Replace(@Summaries,'(','(CASE WHEN ' + @PvotCol + '=''' + Pvot + ''' THEN '),')[', ' END),0) As [' + Pvot) From #TempPvot Order by Pvot 
Drop Table #TempPvot 
Set @SQL = Replace('Select ' + Isnull(@GroupBy,'') + @OtherCols + @Vals + ' From (' + @Source + ') PvtFinal ' + case when Isnull(@GroupBy,'')<>'' then 'Group By ' + @GroupBy + ' Order by ' + @GroupBy else '' end,'Select , ','Select ') 
--Print @SQL 
Exec (@SQL) 


Set NoCount Off 
Set Ansi_Warnings on 
0

PIVOT + SQL dynamique:

CREATE PROCEDURE dbo.ProcedureName 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @cols nvarchar(max), 
      @sql nvarchar(max) 

    SELECT @cols =COALESCE(@cols,'') +','+ QUOTENAME(ID) --,[1],[2],[3] 
    FROM T_data 
    GROUP BY ID 

    SET @sql = N' 
    SELECT * 
    FROM T_data 
    PIVOT (
     MAX([Value]) FOR ID IN ('+STUFF(@cols,1,1,'')+') 
    ) as dd' 


    EXEC sp_executesql @sql 

END 

Sortie:

Field 1  2  3 
------------------------------- 
Age  41  42  43 
Height 181  165  169 
Name John Kelly Dan