如何在 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 BY
和GROUP 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)
注意
我会使用 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;
下面是我在其中创建并插入值的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 BY
和GROUP 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)
注意
我会使用 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;