sql获取两个日期之间的所有月份和年份,并根据两个日期之间的月份频率计算总数
雇员:sql获取两个日期之间的所有月份和年份,并根据两个日期之间的月份频率计算总数,sql,sql-server,tsql,Sql,Sql Server,Tsql,雇员: emid stdt enddt 1 12jan2019 15dec2019 2 12mar2019 12apr2019 3 12mar2018 12apr2018 4 12feb2019 Null 工资表: empid salarypermonth 1 10000 2 20000 3 15000 4 10000 我想列出stdt和endt之间的所有月份和年份,总数应该是 月*工资 所需的o/p,如: month
emid stdt enddt
1 12jan2019 15dec2019
2 12mar2019 12apr2019
3 12mar2018 12apr2018
4 12feb2019 Null
工资表:
empid salarypermonth
1 10000
2 20000
3 15000
4 10000
我想列出stdt和endt之间的所有月份和年份,总数应该是
月*工资
所需的o/p,如:
month year total expenditure
jan 2019 10000
feb 2019 10000
mar 2019 30000 -- total salary of 1 and 2 as employee 1 and 2 both got salary in mar
....
....
mar 2018 15000
....
等等
基本上,我想报告雇主每月和每年的工资支出。
假设员工根据薪资表获得薪资,而不考虑加入日期。您可以使用递归CTE展开数据,然后聚合:
with cte as (
select datefromparts(year(e.stdt), month(e.stdt), 1) as yyyymm,
e.enddt, e.emid, s.salary
from employee e join
salary s
on e.emid = s.empid
union all
select dateadd(month, 1, yyyymm), enddt, emid, salary
from cte
where eomonth(yyyymm) < enddt
)
select yyyymm, sum(salary)
from cte
group by yyyymm
order by yyyymm;
另一种方法是使用Tall和>=删除SQLite标记。根据大量证据,这似乎是SQL Server。事实上,您以2019年1月12日等格式编写了日期,这表明您将其存储为varchar而不是日期;是这样吗?我希望不是。或者,您要查找的查询不会像现在这样与列匹配;因为一个表中有日期/varchar,另一个表中有varchar和年份。“这里有些不太理想的设计选择。我们这里不是在谈论甲骨文,”Joedbahaha说。Oracle也不以某种格式存储日期。如果您在Oracla数据库中看到它们,那是因为有人选择了错误的数据类型。@Larnu。我不会做出这样的假设。人们似乎根据个人喜好在问题中写上日期。为什么提问者不使用YYYY-MM-DD格式——这是标准的ISO 8601格式,明确无误,且区域设置安全——我无法理解。2019年1月12日为了便于参考,我在sql server中以01-12-2019格式记录了日期
USE Sandbox;
GO
CREATE TABLE dbo.Employee (emid int,
stdt date,
enddt date);
INSERT INTO dbo.Employee (emid,
stdt,
enddt)
VALUES (1, '20190112', '20191215'),
(2, '20190312', '20190412'),
(3, '20180312', '20190418'),
(4, '20190212', NULL);
GO
CREATE TABLE dbo.Salary (empid int,
salarypermonth int);
GO
INSERT INTO dbo.Salary (empid,
salarypermonth)
VALUES (1, 10000),
(2, 20000),
(3, 15000),
(4, 10000);
GO
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP (SELECT MAX(DATEDIFF(MONTH, stdt,GETDATE())) FROM dbo.Employee)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 AS I
FROM N N1, N N2), --100 months. Add more for more months
Dates AS(
SELECT DATEADD(MONTH,T.I,E.stdt) AS MonthStart,
EOMONTH(DATEADD(MONTH,T.I,E.stdt)) AS MonthEnd
FROM Tally T
CROSS APPLY (SELECT MIN(stdt) AS stdt FROM dbo.Employee) E)
SELECT DATENAME(MONTH, D.MonthStart)AS [Month],
DATEPART(YEAR,D.MonthStart) AS [Year],
SUM(S.salarypermonth) AS Salaries
FROM Dates D
LEFT JOIN dbo.Employee E ON (D.MonthStart <= E.enddt OR E.enddt IS NULL)
AND D.MonthEnd >= E.stdt
LEFT JOIN dbo.Salary S ON E.emid = S.empid
GROUP BY DATENAME(MONTH, D.MonthStart),
DATEPART(YEAR,D.MonthStart)
ORDER BY CONVERT(date,CONCAT('01 ',DATENAME(MONTH, D.MonthStart),DATEPART(YEAR,D.MonthStart)),106) ASC;
GO
DROP TABLE dbo.Employee;
DROP TABLE dbo.Salary;