【问题标题】:NULL not collapsing in pivot (possible JOIN issue)NULL 未在枢轴中折叠(可能的 JOIN 问题)
【发布时间】:2020-04-14 13:37:13
【问题描述】:

我有四张桌子:

Survey
------
Id | ClientId | SurveyDate

SurveyQuestion
--------------
Id | QuestionText

SurveyAnswer
--------------
Id | AnswerText | AnswerScore

SurveyResponse
---------------
Id | SurveyId | QuestionId | AnswerId

问题表目前有 6 个问题,以后可能会添加更多问题。响应表仅包含已回答问题的调查的行。

我的最终目标是将调查加入到回复中,然后加入到答案中,然后转向所有问题。

到目前为止,我有以下代码:

DECLARE @HighScore INT = (SELECT COUNT(*) FROM SurveyQuestion)
    DECLARE @LowScore INT = 0 - @HighScore

    DECLARE @cols NVARCHAR (MAX)

    SELECT @cols = COALESCE (@cols + ',[' + a.QuestionText + ']', 
                    '[' + a.QuestionText + ']')
                    FROM (SELECT DISTINCT QuestionText, SortOrder FROM SurveyQuestion) a
                    ORDER BY SortOrder

    DECLARE @NulltoZeroCols NVARCHAR(MAX)

    SET @NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+ a.QuestionText +'],NULL) AS ['+ a.QuestionText +']' 
    FROM (SELECT DISTINCT QuestionText, SortOrder FROM SurveyQuestion) a
                    ORDER BY SortOrder FOR XML PATH('')),2,8000)

    DECLARE @query NVARCHAR(MAX)
    SET @query = '
    SELECT [ClientId], [SurveyDate],'+ @NulltoZeroCols +', [QuestionsAnswered], [TotalScore], CONVERT(DECIMAL(10,2),[QuestionsAnswered])/'+CONVERT(NVARCHAR, @HighScore)+'*[TotalScore] AS [AdjustedScore] FROM 
                    (
                    SELECT CS.Id AS ClientId, SurveyDate, SurveyId, QuestionText, AnswerScore, AnswerText, COUNT(*) OVER (PARTITION BY ClientId, SurveyDate) AS QuestionsAnswered, SUM(AnswerScore) OVER (PARTITION BY ClientId, SurveyDate) AS TotalScore
                    FROM Survey CS
                    INNER JOIN SurveyResponse CSR
                    ON CS.Id = CSR.SurveyId
                    INNER JOIN SurveyQuestion CSQ
                    ON CSR.QuestionId = CSQ.Id
                    INNER JOIN SurveyAnswer CSA
                    ON CSR.AnswerId = CSA.Id
                    ) x
                    PIVOT
                (  
                    MAX(x.AnswerText)
                    FOR  [QuestionText] IN (' + @cols + ')
                ) p
                ORDER BY [SurveyDate] DESC;' 

    EXEC SP_EXECUTESQL @query

我的预期输出是:

ClientId    SurveyDate  'Q1Text' 'Q2Text' 'Q3Text' 'Q4Text' 'Q5Text' 'Q6Text'   QuestionsAnswered   TotalScore  AdjustedScore
124 2020-04-14  No  No  No  No  No  No  6   -6  -6.000000
134 2020-04-14  No  No  No  No  Yes Yes 6   -2  -2.000000
137 2020-04-14  Yes No  No  No  Don't Know No   6   -3  -3.000000
17  2018-11-01  Yes NULL    Yes No  NULL    NULL    3   1   0.500000

但我的实际输出并没有折叠 NULL 值。

ClientId    SurveyDate  'Q1Text' 'Q2Text' 'Q3Text' 'Q4Text' 'Q5Text' 'Q6Text'   QuestionsAnswered   TotalScore  AdjustedScore
124 2020-04-14  No  No  No  No  No  No  6   -6  -6.000000
134 2020-04-14  No  No  No  No  NULL    NULL    6   -2  -2.000000
134 2020-04-14  NULL    NULL    NULL    NULL    Yes Yes 6   -2  -2.000000
137 2020-04-14  NULL    No  No  No  NULL    No  6   -3  -3.000000
137 2020-04-14  NULL    NULL    NULL    NULL    Don't Know  NULL    6   -3  -3.000000
137 2020-04-14  Yes NULL    NULL    NULL    NULL    NULL    6   -3  -3.000000
17  2018-11-01  NULL    NULL    NULL    No  NULL    NULL    3   1   0.500000
17  2018-11-01  Yes NULL    Yes NULL    NULL    NULL    3   1   0.500000

我相信这是因为问题在转变之前没有得到处理。我已经尝试将问题加入到 LEFT 和 RIGHT 的响应中,但无济于事(未显示 NULL 值)。

我可能在某个地方过于复杂了,但我无法只见树木不见森林!任何帮助将不胜感激。

编辑:根据加布里埃尔

子查询输出为:

ClientId    SurveyDate  SurveyId    QuestionText    AnswerScore AnswerText  QuestionsAnswered   TotalScore
17  2018-11-01  17  Q1Text  1   Yes 3   1
17  2018-11-01  17  Q3Text  1   Yes 3   1
17  2018-11-01  17  Q4Text  -1  No  3   1
134 2020-04-14  134 Q1Text  -1  No  6   -2
134 2020-04-14  134 Q2Text  -1  No  6   -2
134 2020-04-14  134 Q3Text  -1  No  6   -2
134 2020-04-14  134 Q4Text  -1  No  6   -2
134 2020-04-14  134 Q5Text  1   Yes 6   -2
134 2020-04-14  134 Q6Text  1   Yes 6   -2
124 2020-04-14  124 Q1Text  -1  No  6   -6
124 2020-04-14  124 Q2Text  -1  No  6   -6
124 2020-04-14  124 Q3Text  -1  No  6   -6
124 2020-04-14  124 Q4Text  -1  No  6   -6
124 2020-04-14  124 Q5Text  -1  No  6   -6
124 2020-04-14  124 Q6Text  -1  No  6   -6
137 2020-04-14  137 Q1Text  1   Yes 6   -3
137 2020-04-14  137 Q2Text  -1  No  6   -3
137 2020-04-14  137 Q3Text  -1  No  6   -3
137 2020-04-14  137 Q4Text  -1  No  6   -3
137 2020-04-14  137 Q5Text  0   Don't Know  6   -3
137 2020-04-14  137 Q6Text  -1  No  6   -3

【问题讨论】:

  • 如果您在数据透视之前发布了信息的外观,将会有所帮助。您的“x”子查询
  • 仅供参考 '[' + a.QuestionText + ']'注射安全。使用QUOTENAME 而不是'['']'

标签: sql sql-server join pivot


【解决方案1】:

很抱歉,我之前的回答不正确。 您需要做的就是从“x”子查询中删除 AnswerScore,无论如何都不要使用它。

DECLARE @HighScore INT = (SELECT COUNT(*) FROM SurveyQuestion)
DECLARE @LowScore INT = 0 - @HighScore

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + a.QuestionText + ']', 
                '[' + a.QuestionText + ']')
                FROM (SELECT DISTINCT QuestionText, SortOrder FROM SurveyQuestion) a

DECLARE @NulltoZeroCols NVARCHAR(MAX)

SET @NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+ a.QuestionText +'],NULL) AS ['+ a.QuestionText +']' 
FROM (SELECT DISTINCT QuestionText, SortOrder FROM SurveyQuestion) a
                ORDER BY SortOrder FOR XML PATH('')),2,8000)

DECLARE @query NVARCHAR(MAX)
SET @query = '
 SELECT [ClientId], [SurveyDate],'+ @NulltoZeroCols +', [QuestionsAnswered], [TotalScore], CONVERT(DECIMAL(10,2),[QuestionsAnswered])/'+CONVERT(NVARCHAR, @HighScore)+'*[TotalScore] AS [AdjustedScore] FROM 
                (
                SELECT CS.Id AS ClientId, SurveyDate, SurveyId, QuestionText,  AnswerText, COUNT(*) OVER (PARTITION BY ClientId, SurveyDate) AS QuestionsAnswered, SUM(AnswerScore) OVER (PARTITION BY ClientId, SurveyDate) AS TotalScore
                FROM Survey CS
                INNER JOIN SurveyResponse CSR
                ON CS.Id = CSR.SurveyId
                INNER JOIN SurveyQuestion CSQ
                ON CSR.QuestionId = CSQ.Id
                INNER JOIN SurveyAnswer CSA
                ON CSR.AnswerId = CSA.Id
                ) x
                PIVOT
            (  
                MAX(x.AnswerText)
                FOR  [QuestionText] IN (' + @cols + ')
            ) p
            ORDER BY [SurveyDate] DESC;' 

EXEC SP_EXECUTESQL @query

我在这里http://sqlfiddle.com/#!18/fcb385/19 玩过它,这个小改动会产生所需的结果。基本上,AnswerScore 的作用类似于枢轴的分组列。

【讨论】:

  • 看准了,干杯伙伴!这样就解决了……下次我会记住的,以前从来没有遇到过这个问题。
猜你喜欢
  • 2018-06-17
  • 1970-01-01
  • 1970-01-01
  • 2013-12-24
  • 1970-01-01
  • 2014-09-26
  • 2019-08-07
  • 1970-01-01
相关资源
最近更新 更多