从连接的Month和Year字符串按日期排序的SQL

时间:2017-09-05 14:33:35

标签: sql sql-server

我有一个有趣的查询,其聚合订单不正确,因为它按字母数字顺序排列日期,因为它们是字符串(VARCHARS)。它如下。

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行,以便以某种方式解析“月份”中的年份和月份。列,以及按年份和月份的订单,而不更改数据返回的结构。

这是完全可能的,还是我认为不可能的方法或错误的思考方式?

3 个答案:

答案 0 :(得分:2)

您可以将year(DeployDate)month(DepolyDate)添加到group by子句中,因为您已经在group by子句中使用datename(year, DeployDate)datename(month, DeployDate)它应该不会对所有,除了它允许你在order 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

答案 1 :(得分: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列向下舍入到相关月份的第1天开始的午夜 - 因此同一月内的所有DeployDate值都会生成相同的值。对此列进行分组相当于对字符串进行分组,但它仍然是datetime,因此可以在外部ORDER BY中正确使用。 (并且仍可用于提取外部SELECT

中的月份和年份组件

答案 2 :(得分:1)

您的时间跨度是有序的,所以我只想在每个中选择一个任意值并执行:

menu.popoverPresentationController?.popoverLayoutMargins = UIEdgeInsets(top: 0, left: -90, bottom: 0, right: -90)

我应该注意到我更喜欢格式YYYY-MM;一个重要原因是它可以正确订购。