Imaginez un scénario dans lequel je souhaite get un rapport dynamic à partir de [FormValues]
sous forme de données, en fonction de la colonne [Title]
de [ReportItems]
tant qu'en-tête.
Je suis vraiment confus comment le faire et essayé de nombreuses façons, mais aucun d'entre eux fonctionne bien.
Je devrais pouvoir donner une procédure à [ReportID] et get le résultat.
[FormID]
et [FieldID]
sont des keys relationnelles entre deux tables.
Toute aide aimable serait très appréciée.
CREATE TABLE #ReportItems( ReportItemID [uniqueidentifier] NOT NULL primary key, ReportID [uniqueidentifier] NOT NULL, FormID [uniqueidentifier] NOT NULL, FieldID [uniqueidentifier] NOT NULL, Title nvarchar(100) NOT NULL ) GO insert into #ReportItems select '5674d274-b146-4251-be0d-a15000e7cefa', '597d37c0-563b-42f0-99be-a15000dc7a65', '01304636-fabe-4a3e-9487-a14b012f9a61', 'ba6b9b1a-92ef-4905-830a-a15000d05f7a', 'First Name' insert into #ReportItems select '5674d274-b146-4252-be0d-a15000e7cefa', '597d37c0-563b-42f0-99be-a15000dc7a65', '01304636-fabe-4a3e-9487-a14b012f9a61', 'ba6b9b1a-92ef-4905-830a-a15000d05f7b', 'Last Name' insert into #ReportItems select '5674d274-b146-4253-be0d-a15000e7cefa', '597d37c0-563b-42f0-99be-a15000dc7a65', '01304636-fabe-4a3e-9487-a14b012f9a61', 'ba6b9b1a-92ef-4905-830a-a15000d05f7c', 'Age' GO CREATE TABLE #FormValues( ValueID uniqueidentifier NOT NULL primary key, FormID uniqueidentifier NULL, FieldID uniqueidentifier NOT NULL, UserName nvarchar(100) NOT NULL, Value nvarchar(max) null ) GO insert into #FormValues select 'af6dc400-3972-49ff-9711-a1520002359e', '01304636-fabe-4a3e-9487-a14b012f9a61', 'ba6b9b1a-92ef-4905-830a-a15000d05f7a', 'user 1', 'Mike' insert into #FormValues select 'af6dc400-3972-49ff-9721-a1520002359e', '01304636-fabe-4a3e-9487-a14b012f9a61', 'ba6b9b1a-92ef-4905-830a-a15000d05f7b', 'user 1', 'Oscar' insert into #FormValues select 'af6dc400-3972-49ff-9731-a1520002359e', '01304636-fabe-4a3e-9487-a14b012f9a61', 'ba6b9b1a-92ef-4905-830a-a15000d05f7c', 'user 1', '20' insert into #FormValues select 'af6dc400-3972-49ff-9741-a1520002359e', '01304636-fabe-4a3e-9487-a14b012f9a61', 'ba6b9b1a-92ef-4905-830a-a15000d05f7a', 'user 2', 'Merry' insert into #FormValues select 'af6dc400-3972-49ff-9761-a1520002359e', '01304636-fabe-4a3e-9487-a14b012f9a61', 'ba6b9b1a-92ef-4905-830a-a15000d05f7c', 'user 2', '23' insert into #FormValues select 'af6dc400-3972-49ff-9771-a1520002359e', '01304636-fabe-4a3e-9487-a14b012f9a61', 'ba6b9b1a-92ef-4905-830a-a15000d05f7a', 'user 3', 'Alen' insert into #FormValues select 'af6dc400-3972-49ff-9781-a1520002359e', '01304636-fabe-4a3e-9487-a14b012f9a61', 'ba6b9b1a-92ef-4905-830a-a15000d05f7b', 'user 3', 'Escott' insert into #FormValues select 'af6dc400-3972-49ff-9791-a1520002359e', '01304636-fabe-4a3e-9487-a14b012f9a61', 'ba6b9b1a-92ef-4905-830a-a15000d05f7c', 'user 3', '28' GO Select * from #ReportItems Select * from #FormValues GO
Et je veux un tel rapport comme résultat:
User Name | First Name | Last Name | Age User 1 | Mike | Oscar | 20 User 2 | Merry | | 23 User 3 | Alen | Escott | 28 User n | ... | ... | ... drop table #ReportItems drop table #FormValues
Pour get le résultat souhaité, vous devez utiliser la fonction PIVOT
.
Si toutes vos valeurs ( title
) sont connues à l'avance, vous pouvez coder en dur une requête statique:
select * from ( select r.Title, f.UserName, f.Value from ReportItems r left join FormValues f on r.FormID = f.FormID and r.FieldID = f.FieldID ) src pivot ( max(value) for title in ([First Name], [Last Name], Age) ) piv;
Voir SQL Fiddle avec démo .
Mais il semble que vous aurez un nombre inconnu de titles
que vous voulez transformer en colonnes. Si c'est le cas, alors vous voudrez utiliser SQL dynamic:
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX) select @cols = STUFF((SELECT distinct ',' + QUOTENAME(Title) from ReportItems FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'') set @query = 'SELECT UserName,' + @cols + ' from ( select r.Title, f.UserName, f.Value from ReportItems r left join FormValues f on r.FormID = f.FormID and r.FieldID = f.FieldID ) x pivot ( max(value) for Title in (' + @cols + ') ) p ' execute(@query)
Voir SQL Fiddle avec démo
Le résultat pour les deux serait:
| USERNAME | FIRST NAME | LAST NAME | AGE | ------------------------------------------- | user 1 | Mike | Oscar | 20 | | user 2 | Merry | (null) | 23 | | user 3 | Alen | Escott | 28 |
Si vous avez un SortOrder
spécifique dont vous avez besoin et que vous l'avez stocké dans une table, alors lorsque vous obtenez votre list de colonnes, vous utiliserez ce qui suit et il returnnera les colonnes dans le bon ordre:
select @cols = STUFF((SELECT ',' + QUOTENAME(Title) from ReportItems group by Title, sortorder order by sortorder FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')
Voir SQL Fiddle avec démo
DECLARE @SQL NVARCHAR(MAX) SET @SQL='SELECT F.UserName' SELECT @SQL = @SQL+', MAX(CASE WHEN FieldID='''+CONVERT(VARCHAR(50), FieldID)+''' THEN F.Value END) AS ['+Title+'] ' FROM #ReportItems SET @SQL = @SQL+' FROM #FormValues F GROUP BY F.UserName ORDER BY 1' --select @sql EXEC sp_ExecuteSQL @SQL
Modification ultérieure: procédure de rapport basée sur l'ID de rapport et les colonnes de sorting
CREATE PROCEDURE spReport @ReportID uniqueidentifier, @SortColumns NVARCHAR(MAX) --shoud be a comma separated list of ReportItems.Title AS BEGIN DECLARE @SQL NVARCHAR(MAX) SET @SQL='SELECT F.UserName' SELECT @SQL = @SQL+', MAX(CASE WHEN F.FieldID='''+CONVERT(VARCHAR(50), FieldID)+''' THEN F.Value END) AS ['+Title+'] ' FROM ReportItems WHERE ReportID=@ReportID --create the dynamic sql only for the items in your report SET @SQL = @SQL+' FROM FormValues F JOIN ReportItems R ON F.FormID=R.FormID WHERE R.ReportID = @ReportID GROUP BY F.UserName ' IF @SortColumns<>'' SET @SQL = @SQL + 'ORDER BY '+@SortColumns -- beware of SQL injection. select @sql EXEC sp_ExecuteSQL @SQL, N'@ReportID uniqueidentifier', @ReportID=@ReportID END
Mais, et je ne peux pas le souligner assez, vous devez accorder une attention particulière au paramètre @SortColumns, car vous vous ouvrez à SQL Injection.