如何在 SQL 服务器中按顺序显示月份?

How to display months sorted in order in SQL Server?

下面是我在其中创建并插入值的table:

CREATE TABLE employees_list   
(
    employeeID int identity(1,1),   
    employeeName varchar(25)
)  
GO   
  
INSERT INTO employees_list VALUES ('Kevin'),('Charles')  
GO   
   
CREATE TABLE hourlyRates   
(
    employeeID int,   
    rate int,   
    rateDate date
)   
  
INSERT INTO hourlyRates VALUES (1, 28, '2016-01-01'),   
                               (1, 39, '2016-02-01'),  
                               (2, 43, '2016-01-01'),  
                               (2, 57, '2016-02-01')  
  
  
CREATE TABLE workingHours   
(
    employeeID int,   
    startdate datetime,   
    enddate datetime
)  
GO   
  
INSERT INTO workingHours VALUES (1, '2016-01-01 09:00', '2016-01-01 17:00'),  
                                (1, '2016-01-02 09:00', '2016-01-02 17:00'),  
                                (1, '2016-02-01 10:00', '2016-02-01 16:00'),  
                                (1, '2016-02-02 11:00', '2016-02-02 13:00'),  
                                (2, '2016-01-01 10:00', '2016-01-01 16:00'),  
                                (2, '2016-01-02 08:00', '2016-01-02 14:00'),  
                                (2, '2016-02-01 14:00', '2016-02-01 19:00'),  
                                (2, '2016-02-02 13:00', '2016-02-02 16:00')  
GO

SELECT * FROM employees_list
SELECT * FROM hourlyRates
SELECT * FROM workingHours

然后我运行查询计算每个月支付给员工的工资:

SELECT 
    employeeName,
    DATENAME(MONTH, startdate) AS 'Month',
    SUM(DATEDIFF(HOUR, startdate, enddate) * rate) AS 'Total Salary'
FROM 
    hourlyRates, workingHours, employees_list
WHERE 
    hourlyRates.employeeID = workingHours.employeeID
    AND employees_list.employeeID = workingHours.employeeID
    AND (hourlyRates.rateDate BETWEEN DATEFROMPARTS(DATEPART(YEAR, workingHours.startDate), DATEPART(MONTH, workingHours.startDate),1) 
                                  AND DATEFROMPARTS(DATEPART(YEAR, workingHours.endDate), DATEPART(MONTH, workingHours.endDate),1))
 GROUP BY 
     employeeName, DATENAME(MONTH, startdate)

我得到了以下输出:

从上面的截图可以看出,我得到了我想要的结果。

但唯一的问题是月份没有按顺序显示。

我尝试添加 ORDER BY DATENAME(MONTH, startdate),但仍然没有对月份的顺序进行排序。

我什至试过 ORDER BY DATEPART(MM, startdate) 但它显示错误,指出它不包含在聚合函数或 GROUP BY 子句中。

我需要对我的查询做哪些小改动?

Why add ORDER BY DATENAME(MONTH,startdate) not work

因为 ORDER 取决于字符而不是数字的月份。

您可以尝试在ORDER BYGROUP BY中添加MONTH(startdate),因为您可能需要在GROUP BY[=23=中添加non-aggregate功能]

SELECT employeeName,DATENAME(MONTH,startdate) AS 'Month',
       SUM(DATEDIFF(HOUR,startdate,enddate) * rate) AS 'Total Salary'
FROM hourlyRates
INNER JOIN workingHours
ON  hourlyRates.employeeID = workingHours.employeeID
INNER JOIN employees_list
ON employees_list.employeeID = workingHours.employeeID
WHERE
(hourlyRates.rateDate
 BETWEEN DATEFROMPARTS(DATEPART(YEAR, workingHours.startDate), DATEPART(MONTH,workingHours.startDate),1) 
 AND DATEFROMPARTS(DATEPART(YEAR, workingHours.endDate), DATEPART(MONTH,workingHours.endDate),1))
GROUP BY employeeName,DATENAME(MONTH,startdate),MONTH(startdate)
ORDER BY MONTH(startdate)

sqlfiddle

注意

我会使用 INNER JOIN ANSI 语法而不是 ,,这意味着 CROSS JOIN 因为 JOIN 语法通常被认为更具可读性。

如前所述,ORDER BY DATENAME 将按月份的 文本名称 排序,而不是按月份的实际顺序排序。

最好只按EOMONTH分组排序,然后可以从SELECT

中提取月份名称

进一步改进:

  • 始终使用显式连接语法,而不是 old-style , 逗号连接。
  • 为表格起短别名,使您的查询更具可读性。
  • 您的日期间隔检查可能不太正确,您可能还需要调整费率计算,但没有进一步的信息我不知道。
    更准确的计算可能意味着计算 part-dates.
SELECT
  e.employeeName,
  DATENAME(month, EOMONTH(wh.startdate)) AS Month,
  SUM(DATEDIFF(HOUR, wh.startdate, wh.enddate) * hr.rate) AS [Total Salary]
FROM hourlyRates hr
JOIN workingHours wh ON hr.employeeID = wh.employeeID
  AND hr.rateDate
    BETWEEN DATEFROMPARTS(YEAR(wh.startDate), MONTH(wh.startDate), 1) 
    AND DATEFROMPARTS(YEAR(wh.endDate), MONTH(wh.endDate), 1)
JOIN employees_list e ON e.employeeID = wh.employeeID
GROUP BY
  e.employeeId,
  e.employeeName,
  EOMONTH(wh.startdate)
ORDER BY
  EOMONTH(wh.startdate),
  e.employeeName;

db<>fiddle