2016-03-17 104 views
1

快速背景以便我的問題有意義:系統以問卷形式從用戶收集數據。用戶屬於組織,組織屬於部門,問題/計算(如調查問卷中所示)在部門之間各不相同。 (問題由用戶回答;計算由系統計算)。複雜的SQL樞軸查詢

下表存在:

部門(扇區,名稱)
組織(OrganisationID,名稱,扇區)
(YearID,名稱)

問題( QuestionID,DisplayText,CommonName,SectorID)
答案(AnswerID,應答OrganisationID,YearID,QuestionID)

計算(CalculationID,DisplayText,的CommonName,扇區)
CalculationResults(CalculationResultID,結果,OrganisationID,YearID,CalculationID)

我需要以下面的方式來顯示數據:

view

,使這個partic事情非常複雜(對我而言)是問題以不同的方式在不同的行業中以不同的方式顯示給用戶,但其中一些問題仍然是常見的問題。例如。 「製造業銷售」與「銷售(製造業)」是一樣的。我需要使用CommonName字段來確定通用性。

我已經設法使用SQL Pivot來接近我想要的 - SQL Fiddle(如果您運行SQL,您會注意到空值和「通用性」問題)。但是有些東西是從我嘗試丟失:

  1. 共性和列名 - 我需要的列名是CommonName領域,而不是QuestionID領域。

  2. 我只從選擇的答案表 - 我還需要從CalculationResults表,該表結構完全相同選擇。

編輯:與SQL小提琴數據期望的結果是: enter image description here (這兩個塊帶有橙色角落需要一路向左移動,這樣一共有3列是。對問題 - 3個獨特CommonName值接下來的3列是用於計算的3個獨特的CommonName值我希望我是有道理的,如果不是讓我知道)

EDIT2:另一個編輯只。爲了娛樂。我當然想過重新設計數據庫,但現階段它不是一種選擇 - 在這個遺留系統上風險太大。在任何人看到設計和思想的情況下。我希望能夠以Pivot的形式獲得解決方案。

+1

你能提供與演示您在sqlfiddle提供確切想要的結果(列名和值)畫面? – lad2025

+0

@ lad2025,編輯原帖 – user982119

回答

1

,而不是PIVOT有時你可以使用[Aggregate](CASE EXPRESSION)獲得相同的數據。有時它更快。

對於您的問題,您可以使用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

+0

絕對是答案! 「避免像'+1'這樣的評論」! +1! (恩,不,我尊重規則,在你看完之後我會刪除這條評論。+1。謝謝你的努力。) – user982119

+0

很高興我可以幫忙 – JamieD77

1

基本上我們想要得到QuestionIDGrouped BySectorIDName的順序。

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

這應該這樣做:

你可以像這樣做到這一點使用PARTITION BY

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, '[email protected]+' 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 ('[email protected]+') 
) piv 
order by Organisation, Year 
'; 

PRINT(@query); 

EXECUTE (@query); 

結果:

enter image description here

+0

感謝您抽出時間(討厭這個問題太複雜了,但我無法用其他方式表達)。我試圖在SQL小提琴上運行這個錯誤,雖然它看起來很有前途,我會用它。它也缺少列命名,並且它不查詢兩個表,只有Answers。但是,真的,感謝 – user982119

+2

努力,我不確定是誰投票否決了你的問題,但我認爲它寫得很好。特別是我喜歡你包含示例數據和SQL小提琴的事實。真的很容易工作。 –

+0

@ user982119如果它確實對您有用,請將答案標記爲已接受;) –