2015-10-05 20 views
0

SQL下面的工作gr8,但是命令,如何設置放置Jan,Feb,Mar的順序。我知道我需要按順序執行此操作,但是當我按順序添加時,出現錯誤'除非TOP,OFFSET,ORDER BY子句在視圖,內聯函數,派生表,子查詢和公用表表達式中無效或FOR XML也被指定。'通過SQL向PIVOT組發出加入命令

結果如下所示:

enter image description here

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

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(year(TransactionDateTime)) 
      FROM Quotations 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

SET @query = 
    'SELECT * 
    FROM (
     SELECT 
      left(datename(month,TransactionDateTime),3) as [month], year(TransactionDateTime) as [year], 
      isnull(count(*),0) as Total 
     FROM quotations 
     group by left(datename(month,TransactionDateTime),3), year(TransactionDateTime) 
    ) as s 
    PIVOT 
    (
     SUM(Total) 
     FOR [year] IN (' + @cols + ') 
    ) AS QuotationResults' 



EXECUTE(@query) 
+0

您是否嘗試過加入'TOP 100%'的選擇? – markpsmith

回答

1

由於錯誤說,你不能除非有訂單(TOPFOR XML等)的理由下令子查詢。原因是,僅僅因爲你已經訂購了子查詢,沒有理由認爲這個訂單會保留在你的外部查詢中。 SQL Server基本上告訴你,你的ORDER BY是毫無意義的,因此無效。

解決方案是簡單地將一個包含月份編號的列添加到您的子查詢s,然後您可以通過它進行訂購。您還需要明確地說明你的選擇列表,以確保這個新列沒有出現在它:

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

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(year(TransactionDateTime)) 
      FROM Quotations 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,''); 

SET @query = 
    'SELECT [month], ' + @Cols + ' 
    FROM (
     SELECT 
      left(datename(month,TransactionDateTime),3) as [month], 
      datepart(month,TransactionDateTime) as [monthNum], 
      year(TransactionDateTime) as [year], 
      isnull(count(*),0) as Total 
     FROM quotations 
     group by left(datename(month,TransactionDateTime),3), datepart(month,TransactionDateTime), year(TransactionDateTime) 
    ) as s 
    PIVOT 
    (
     SUM(Total) 
     FOR [year] IN (' + @cols + ') 
    ) AS QuotationResults 
    ORDER BY QuotationResults.MonthNum;'; 

EXECUTE(@query); 

附錄

ISNULL()不捕獲空值,因爲在使用ISNULL()的點不存在。 COUNT(*)從不返回null,所以你的ISNULL()實際上是多餘的。

在一個很簡單的例子,如果您有:

TransactionDateTime 
---------------------- 
2015-01-01 
2015-02-01 
2015-02-01 
2014-03-01 

要跳過領先一步,你的支點後,你將結束:

Month 2014 2015 
------------------------ 
Jan  NULL 1 
Feb  NULL 2 
Mar  1  NULL 

所以你最終NULL值,現在回去一步,如果你看看你的聚合後的結果,你有:

Month MonthNum Year Total 
----------------------------------- 
Jan  1   2015 1 
Feb  2   2015 2 
Mar  3   2014 1 

所以沒有行對於2014年1月或2月,因此SUM(NULL)將產生NULL。我建議將所有的聚合都留給pivot函數。所以,你的非動態查詢看起來是這樣的:

SELECT pvt.[Month], pvt.[2014], pvt.[2015] 
FROM ( SELECT [Month] = LEFT(DATENAME(MONTH, TransactionDateTime), 3), 
        [MonthNum] = DATEPART(MONTH, TransactionDateTime), 
        [Year] = DATEPART(YEAR, TransactionDateTime), 
        Value = 1 
      FROM Quotations 
     ) AS t 
     PIVOT 
     (
      COUNT(Value) 
      FOR [year] IN ([2014], [2015]) 
     ) AS pvt 
ORDER BY pvt.MonthNum; 

並投入動態SQL:

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

SET @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(DATEPART(YEAR, TransactionDateTime)) 
      FROM Quotations 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,''); 

SET @query = 
    'SELECT pvt.[Month], ' + @cols + ' 
    FROM ( SELECT [Month] = LEFT(DATENAME(MONTH, TransactionDateTime), 3), 
         [MonthNum] = DATEPART(MONTH, TransactionDateTime), 
         [Year] = DATEPART(YEAR, TransactionDateTime), 
         Value = 1 
       FROM Quotations 
      ) AS t 
      PIVOT 
      (
       COUNT(Value) 
       FOR [year] IN (' + @cols + ') 
      ) AS pvt 
    ORDER BY pvt.MonthNum; 
    (
     SUM(Total) 
     FOR [year] IN (' + @cols + ') 
    ) AS QuotationResults 
    ORDER BY QuotationResults.MonthNum;'; 

EXECUTE sp_executesql @query; 
+0

不可思議,非常感謝!試圖找出爲什麼isnull()被忽略並仍然返回null。不過,我可以稍後將其陷入困境,歡呼聲,J – John