繁体   English   中英

复杂的SQL Pivot查询

[英]Complex SQL Pivot query

快速背景知识使我的问题变得有意义:系统以问卷的形式从用户那里收集数据。 用户属于组织,组织属于部门,并且各个部门的问题/计算方式(在调查表中可以找到)不同。 (问题由用户回答;计算由系统计算)。

存在以下表格:

部门部门 ID,名称)
组织 (组织ID,名称,部门ID)
(YearID,姓名)

问题 (QuestionID,DisplayText,CommonName,SectorID)
答案答案 ID,答案,组织ID,年份ID,问题ID)

计算 (CalculationID,DisplayText,CommonName,SectorID)
CalculationResults (CalculationResultID,Result,OrganizationID,YearID,CalculationID)

我需要通过以下方式显示数据:

视图

(对我而言)使问题特别复杂的是,问题在它们所属的不同部门之间以不同的方式(向用户显示),但是其中一些仍然是常见问题。 例如,“制造销售”将与“销售(制造)”相同。 我需要使用CommonName字段来确定通用性。

我设法使用SQL Pivot接近我想要的-SQL Fiddle (如果运行SQL,您会注意到null和“ commonality”问题)。 但是,我的尝试中缺少一些东西:

  1. 通用性和列名-我需要将列名设置为CommonName字段,而不是QuestionID字段。

  2. 我只从“ 答案”表中进行选择-我还需要从结构相同的CalculationResults表中进行选择。

编辑 :与SQL Fiddle数据所需的结果是: 在此处输入图片说明 (两个带有橙色角的块需要一直向左移动,因此问题总共有3列-3个唯一的CommonName值。接下来的3列是3个唯一的CommonName值,用于计算我希望我有道理,如果没有让我知道。)

Edit2 :另一个有趣的编辑。 我确实考虑过重新设计数据库,但是在当前阶段这不是一个选择-在此旧系统上风险太大。 以防万一有人看到设计并以为如此。 我希望有一个Pivot形式的解决方案。

基本上,我们希望得到Grouped By SectorIDName Grouped ByQuestionID的顺序。

您可以使用PARTITION BY进行以下操作:

ROW_NUMBER() OVER(PARTITION BY q.SectorID, y.Name ORDER BY a.QuestionID)

这应该做到这一点:

    DECLARE @cols AS  NVARCHAR(MAX)
     , @query AS NVARCHAR(MAX);

SELECT                     @cols = STUFF(
                                 (SELECT DISTINCT
                                        ','+QUOTENAME(CAST(ROW_NUMBER() OVER(PARTITION BY q.SectorID
                                                                              , y.Name ORDER BY a.QuestionID) AS VARCHAR(10)))
                                  FROM   Answers a
                                        LEFT JOIN Years y ON a.YearID = y.YearID
                                        LEFT JOIN Organisations o ON a.OrganisationID = o.OrganisationID
                                        LEFT JOIN Questions q ON a.QuestionID = q.QuestionID
                                  FOR XML PATH(''), TYPE).value
      ('.', 'NVARCHAR(MAX)'), 1, 1, '');

SET @query = '
            SELECT Organisation, Year, '+@cols+' from 
(
 SELECT QuestionID = ROW_NUMBER() OVER(PARTITION BY q.SectorID
                                              , y.Name ORDER BY a.QuestionID)
           , o.Name AS Organisation
           , y.Name AS Year
           , a.Answer
       FROM   Answers a
            LEFT JOIN Years y ON a.YearID = y.YearID
            LEFT JOIN Organisations o ON a.OrganisationID = o.OrganisationID
            LEFT JOIN Questions q ON a.QuestionID = q.QuestionID
) src
pivot
(
  max(Answer)
  for QuestionID in ('+@cols+')
) piv
order by Organisation, Year
';

PRINT(@query);

EXECUTE (@query);

结果:

在此处输入图片说明

有时可以使用[Aggregate](CASE EXPRESSION)代替PIVOT获得相同的数据。 有时更快。

对于您的问题,可以将OUTER APPLY与动态MAX(CASE)

DECLARE @Questions NVARCHAR(MAX),
        @Calculations NVARCHAR(MAX),
        @Sql NVARCHAR(MAX)

SELECT  @Questions = COALESCE(@Questions + ', ', '') 
            + 'MAX(CASE WHEN q.CommonName = ''' + CommonName + ''' THEN a.Answer END) AS ' + QUOTENAME(CommonName)
FROM    Questions 
GROUP BY CommonName

SELECT  @Calculations = COALESCE(@Calculations + ', ', '') 
            + 'MAX(CASE WHEN c.CommonName = ''' + CommonName + ''' THEN cr.Result END) AS ' + QUOTENAME(CommonName)
FROM    Calculations  
GROUP BY CommonName

SET     @Sql = N'
        SELECT 
            o.Name As [Organisation],
            y.Name As [Year],
            q.*,
            c.*
        FROM 
            Organisations o
            CROSS JOIN Years y
            OUTER APPLY (
                SELECT ' + @Questions + ' 
                FROM    Answers a 
                        JOIN Questions q ON a.QuestionID = q.QuestionID
                WHERE   a.OrganisationID = o.OrganisationID 
                        AND a.YearID = y.YearID
            ) q
            OUTER APPLY (
                SELECT ' + @Calculations + ' 
                FROM    CalculationResults cr 
                        JOIN Calculations c ON cr.CalculationID = c.CalculationID
                WHERE   cr.OrganisationID = o.OrganisationID 
                        AND cr.YearID = y.YearID
            ) c
'

SQL FIDDLE DEMO

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM