SQL Server:通过不产生正确的结果顺序进行分组

时间:2018-10-10 06:39:50

标签: sql sql-server tsql

我必须编写一个查询,其中将按月和年以及“成绩”对结果进行分组。例如,表数据为:

DECLARE @Scores TABLE (
    [SubmissionDate] DATETIME,
    [Score] INT,
    [Grade] VARCHAR(7)
)
INSERT INTO @Scores VALUES
('2018-08-01', 60, 'AVERAGE'),
('2018-08-01', 50, 'POOR'),
('2018-09-01', 68, 'AVERAGE'),
('2018-09-01', 66, 'AVERAGE'),
('2018-07-01', 64, 'AVERAGE'),
('2018-07-01', 56, 'POOR'),
('2018-08-01', 62, 'AVERAGE'),
('2018-08-01', 80, 'GOOD'),
('2018-09-01', 52, 'POOR'),
('2018-09-01', 54, 'POOR'),
('2018-07-01', 58, 'POOR'),
('2018-08-01', 50, 'POOR'),
('2018-09-01', 82, 'GOOD'),
('2018-09-01', 86, 'GOOD'),
('2018-07-01', 62, 'AVERAGE'),
('2018-07-01', 84, 'GOOD'),
('2018-07-01', 82, 'GOOD'),
('2018-08-01', 88, 'GOOD')

我需要的是每个年级每个月的平均分数。我能够得到平均正确的值。对我来说,几个月不起作用。结果按字母顺序显示(8月显示在7月之前,然后显示9月)正确的顺序应为-> 7月,8月,9月

这是我写的查询:

;WITH CTE AS(
    SELECT 
        LEFT(UPPER(DATENAME(MM, [SubmissionDate])),3) + '-' + DATENAME(YY, [SubmissionDate]) AS [Range]
       ,[Score]
       ,[Grade]
    FROM @Scores
)
SELECT [Range], AVG([Score]) AS [AverageScore], [Grade]
FROM CTE GROUP BY [Range], [Grade]

以下是输出:

Range       AverageScore    Grade
AUG-2018    61              AVERAGE
JUL-2018    63              AVERAGE
SEP-2018    67              AVERAGE
AUG-2018    84              GOOD
JUL-2018    83              GOOD
SEP-2018    84              GOOD
AUG-2018    50              POOR
JUL-2018    57              POOR
SEP-2018    53              POOR

我需要第一列的正确顺序。

3 个答案:

答案 0 :(得分:1)

我建议先输入年份,然后再输入月份名称。然后,ORDER BY使用通过datetime转换为TRY_CONVERT的值:

WITH cte AS (
    SELECT 
        DATENAME(YY, [SubmissionDate]) + '-' +
            LEFT(UPPER(DATENAME(MM, [SubmissionDate])), 3) AS [Range],
        [Score],
        [Grade]
    FROM @Scores
)

SELECT
    [Range],
    AVG([Score]) AS [AverageScore],
[Grade]
FROM cte
GROUP BY
    [Range],
    [Grade]
ORDER BY
    TRY_CONVERT(datetime, [Range]);

enter image description here

Demo

注意:如果您还想在日期之前或之后添加另一个订单级别,则可以这样做,并且这不会影响上面使用的排序逻辑。

答案 1 :(得分:0)

使用此代码:

;WITH CTE AS(
SELECT 
LEFT(UPPER(DATENAME(MM, [SubmissionDate])),3) + '-' + DATENAME(YY, [SubmissionDate]) AS [Range], [SubmissionDate]
,[Score]
,[Grade]
FROM @Scores
)
SELECT [Range], AVG([Score]) AS [AverageScore], [Grade]
FROM CTE GROUP BY [Range], [Grade],[SubmissionDate]
order by [SubmissionDate]

答案 2 :(得分:0)

您可以添加其他列进行排序。

;WITH CTE AS(
    SELECT 
        LEFT(UPPER(DATENAME(MM, [SubmissionDate])),3) + '-' + DATENAME(YY, [SubmissionDate]) AS [Range]
        ,[Score]
        ,[Grade]
        , CONVERT(VARCHAR(6), [SubmissionDate], 112) AS [RangeOrder] -- ISO: 112 = yyyymmdd
    FROM @Scores
)
SELECT 
    [Range], 
    AVG([Score]) AS [AverageScore], 
    [Grade]
FROM CTE 
GROUP BY [Range], [Grade], [RangeOrder]
ORDER BY [RangeOrder]

结果:

Range                              AverageScore Grade
---------------------------------- ------------ -------
JUL-2018                           63           AVERAGE
JUL-2018                           83           GOOD
JUL-2018                           57           POOR
AUG-2018                           61           AVERAGE
AUG-2018                           84           GOOD
AUG-2018                           50           POOR
SEP-2018                           67           AVERAGE
SEP-2018                           84           GOOD
SEP-2018                           53           POOR