您遇到的問題是,你是用字符串月份名稱排序,所以很自然的,它應該按照字母順序排列,如果您需要按時間順序排列,則需要按月份編號(DATEPART(MONTH, tDate)
)排序,這意味着將其添加到GROUP BY
,以便您可以對其進行排序。這不會影響基數,因爲任何給定的月份名稱只能有一個月份的數字。
這就是說,你不應該使用變量賦值連接字符串,it is not guaranteed to return the correct results,更不用說按照你所說的順序。最終的實際結果將取決於優化器採用的內部途徑。請使用FOR XML PATH()
。
DECLARE @start DATETIME = '2016-08-03 00:00',
@end DATETIME = '2016-11-08 00:00',
@day VARCHAR(MAX) = '';
SET @day = STUFF((SELECT ',[' + LEFT(DATENAME(MONTH, tDate), 3) + ']'
FROM someDB.[dbo].[someTable]
WHERE tdate BETWEEN @start AND @end
GROUP BY LEFT(DATENAME(MONTH, tDate), 3), DATEPART(MONTH, tDate)
ORDER BY DATEPART(MONTH, tDate)
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '');
SELECT @day;
值得注意的是,你可能不會得到你想要的結果,如果您的日期範圍跨越多個年了,這是個人喜好,但我傾向於的日期範圍for reasons set out here
避開BETWEEN
如果你要建立並執行動態SQL這樣的,我會advise you use sp_executesql
這樣就可以適當類型的傳遞你的參數,而不是幹這種可怕的級聯應用您的日期篩選:
'+''''+ convert(varchar,@start) +''' and '
,而不是你可以聲明,並通過paramters:
DECLARE @query NVARCHAR(MAX) = 'SELECT ... WHERE tDate BETWEEN @start AND @end';
EXECUTE sp_executesql @Query, N'@Start DATETIME, @end DATETIME', @Start, @end;
NB You should always specify a length when converting to, or declaring a varchar
最後,DATETIME
工作字面日期格式xxxx-xx-xx
是模糊時,既可以指yyyy-MM-dd
和yyyy-dd-MM
,使視區域設置您的起始參數可以是8月3日和3月8日。 只有文化不變格式DATETIME
是yyyyMMdd
。更多閱讀見Bad habits to kick : mis-handling date/range queries
所以完整的查詢可能看起來像:
DECLARE @start DATETIME = '20160803 00:00',
@end DATETIME = '20161108 00:00',
@day VARCHAR(MAX) = '';
SET @day = STUFF((SELECT ',[' + LEFT(DATENAME(MONTH, tDate), 3) + ']'
FROM someDB.[dbo].[someTable]
WHERE tdate BETWEEN @start AND @end
GROUP BY LEFT(DATENAME(MONTH, tDate), 3), DATEPART(MONTH, tDate)
ORDER BY DATEPART(MONTH, tDate)
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '');
DECLARE @Query NVARCHAR(MAX) =
'SELECT *
FROM (SELECT Customer, LEFT(DATENAME(MONTH,tdate), 3) AS OrderMonth, SUM(saleAmount) AS Amount
FROM SomeDB.[dbo].[SomeTable]
WHERE tdate >= @start
AND tDate <= @end
GROUP BY Customer, LEFT(DATENAME(MONTH,tdate), 3)) AS pp
PIVOT (SUM(Amount) FOR OrderMonth IN (' + @day + ')) AS pvt';
EXECUTE sp_executesql @Query, N'@Start DATETIME, @end DATETIME', @Start, @end;
我並沒有特意鏈接到這麼多的阿龍貝特朗的文章,它只是恰巧你已經陷入了很多他曾經博客的陷阱。因此,儘管我可以通過鏈接到full list of his "Bad Habits to Kick" articles來完成它們,但它們非常值得一讀。
感謝您的快速回復。 我們的目標是擁有一列客戶,以及一列月份。 年是不是和問題。 它看起來像 Jan Feb Cust A 500 200 Cust B 200 300 –
我很抱歉我的問題沒有完成。如果可以提供幫助,我添加了其餘的代碼。提前致謝。 –
令人驚歎的解釋。我遇到的問題是DateKey?這是什麼代表。我只是有紅色的下劃線。 –