2017-09-05 142 views
1

我有一個有趣的查詢,其中包含錯誤的聚合命令,因爲它以字母順序排列日期,因爲它們是字符串(VARCHARS)。它如下。SQL order by concatenated Month and Year字符串

DROP PROCEDURE dbo.DeploymentReport 
GO 

CREATE PROCEDURE dbo.DeploymentReport 
@Date DATE 
AS 
BEGIN 
SELECT TOP 6 DATENAME(MONTH,DeployDate) + ' - ' + DATENAME(YEAR,DeployDate) AS 'Month', 
     ISNULL(SUM(CASE WHEN OverallRiskRating = 3 THEN 1 END),0) AS 'High', 
     ISNULL(SUM(CASE WHEN OverallRiskRating = 2 THEN 1 END),0) AS 'Med', 
     ISNULL(SUM(CASE WHEN OverallRiskRating = 1 THEN 1 END),0) AS 'Low'  
FROM dbo.ChangeEvaluationForm cef 
INNER JOIN dbo.Package pac 
ON cef.ChangeId = pac.ChangeId 
INNER JOIN dbo.SDMTicket sdm 
ON pac.PackageId = sdm.PackageId 
WHERE DeployDate < @Date 
GROUP BY DATENAME(MONTH, DeployDate) + ' - ' + DATENAME(YEAR,DeployDate) 
ORDER BY DATENAME(MONTH, DeployDate) + ' - ' + DATENAME(YEAR,DeployDate) DESC 
END 
GO 

DECLARE @DateSelected DATETIME 
SET @DateSelected = CONVERT(DATE,'2017-12-30') 
EXECUTE dbo.DeploymentReport @Date = @DateSelected; 

結果如下所示

enter image description here

正如你所看到的月份按日期排序的字母數字代替。

現在我對彙總查詢是絕對殘酷的,所以我的鬥爭是改變ORDER BY行,以便以某種方式解析「月」列中的年份和月份,以及年份和月份中的訂單,而不更改數據返回的結構。

這是不是可能,或者是我認爲不可能的方法或者錯誤的思維方式?

+1

只是不按DATENAME命令。只需使用「ORDER BY DATEPART(mm,DeployDate)」等等 –

回答

2

您可以通過條款,添加year(DeployDate)month(DepolyDate)到組,因爲你已經在使用組datename(year, DeployDate)datename(month, DeployDate) by子句應該沒有效果都沒有,其他的則是,它可以讓你使用他們的按條款排序:

CREATE PROCEDURE dbo.DeploymentReport 
@Date DATE 
AS 
BEGIN 
SELECT TOP 6 DATENAME(MONTH,DeployDate) + ' - ' + DATENAME(YEAR,DeployDate) AS 'Month', 
     ISNULL(SUM(CASE WHEN OverallRiskRating = 3 THEN 1 END),0) AS 'High', 
     ISNULL(SUM(CASE WHEN OverallRiskRating = 2 THEN 1 END),0) AS 'Med', 
     ISNULL(SUM(CASE WHEN OverallRiskRating = 1 THEN 1 END),0) AS 'Low'  
FROM dbo.ChangeEvaluationForm cef 
INNER JOIN dbo.Package pac 
ON cef.ChangeId = pac.ChangeId 
INNER JOIN dbo.SDMTicket sdm 
ON pac.PackageId = sdm.PackageId 
WHERE DeployDate < @Date 
GROUP BY DATENAME(MONTH, DeployDate) + ' - ' + DATENAME(YEAR,DeployDate), Year(DeployDate), Month(DeployDate) 
ORDER BY Year(DeployDate) DESC, Month(DeployDate) DESC 
END 
GO 
+0

這個工程也很棒,我實際上選擇使用這個解決方案來代替可讀性 – David

+0

很高興爲您提供幫助: - ) –

1

GROUP BY邏輯到使用更「日期樣」分組列的子查詢,然後應用TOPORDER BY在外部查詢:

SELECT TOP 6 DATENAME(MONTH,DeployDate) + ' - ' + DATENAME(YEAR,DeployDate) AS 'Month', 
     High,Med,Low 
FROM (
     SELECT DATEADD(month,DATEDIFF(month,0,DeployDate),0) as DeployDate, 
     ISNULL(SUM(CASE WHEN OverallRiskRating = 3 THEN 1 END),0) AS 'High', 
     ISNULL(SUM(CASE WHEN OverallRiskRating = 2 THEN 1 END),0) AS 'Med', 
     ISNULL(SUM(CASE WHEN OverallRiskRating = 1 THEN 1 END),0) AS 'Low'  
FROM dbo.ChangeEvaluationForm cef 
INNER JOIN dbo.Package pac 
ON cef.ChangeId = pac.ChangeId 
INNER JOIN dbo.SDMTicket sdm 
ON pac.PackageId = sdm.PackageId 
WHERE DeployDate < @Date 
GROUP BY DATEADD(month,DATEDIFF(month,0,DeployDate),0) 
) t 
ORDER BY DeployDate DESC 

這裏,DATEADD(month,DATEDIFF(month,0,DeployDate),0)DeployDate柱向下在相關月份的第一天開始的午夜 - 因此同一月份內的所有DeployDate值都會生成相同的值。然後,在此列上分組就相當於對您的字符串進行分組,但它仍然是datetime,因此可以在外部ORDER BY中正確使用。 (而且仍然可以使用外SELECT提取年份和月份組成部分)

+0

這就像一個魅力。非常感謝你! – David

1

你的時間跨度是有序的,所以我只選擇在每一個任意值,並做到:

ORDER BY MIN(DeployDate) DESC 

我應該注意到我更喜歡YYYY-MM格式;一個重要的原因是它可以正確地命令。