2

ヘッダーの列に[FormValues]基づいて、データとして動的レポートを取得するシナリオを想像してください。[Title][ReportItems]

どうしようか迷って色々試してみたのですがどれもうまくいきません。

プロシージャに [ReportID] を指定して、結果を取得できるはずです。

[FormID]および[FieldID]は、2 つのテーブル間のリレーショナル キーです。

どんな親切な助けも大歓迎です。

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

そして、結果としてそのようなレポートが必要です:

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
4

2 に答える 2

3

希望する結果を得るには、関数を使用する必要がありPIVOTます。

すべての値(title)が事前にわかっている場合は、静的クエリをハードコーディングできます。

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;

SQL FiddlewithDemoを参照してください。

titlesしかし、列に変換したい数が不明になるようです。その場合は、動的SQLを使用する必要があります。

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)

SQL FiddlewithDemoを参照してください

両方の結果は次のようになります。

| USERNAME | FIRST NAME | LAST NAME | AGE |
-------------------------------------------
|   user 1 |       Mike |     Oscar |  20 |
|   user 2 |      Merry |    (null) |  23 |
|   user 3 |       Alen |    Escott |  28 |

必要な特定のSortOrderものがあり、それをテーブルに格納している場合、列のリストを取得するときに、以下を使用すると、正しい順序で列が返されます。

select @cols = STUFF((SELECT ',' + QUOTENAME(Title) 
                    from ReportItems
                    group by Title, sortorder
                    order by sortorder
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

SQL FiddlewithDemoを参照してください

于 2013-02-13T16:24:52.223 に答える
1
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

後で編集: レポート ID に基づくレポートの手順と列の並べ替え

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

しかし、これを十分に強調することはできませんが、@SortColumns パラメーターに特別な注意を払う必要があります。これは、SQL インジェクションに対して自分自身を開いているためです。

于 2013-02-13T16:27:13.080 に答える