活动介绍

帮我做一个企业人事管理系统,SQL server的程序,只要一个程序,不要分段,全部包含在一个里面,需要查询人员,人员包括(名字,年龄,部门,工资,信息随机),和考勤功能,早上九点到中午十一点五十和下午两点半到晚上七点,其余时间均为缺勤。

时间: 2025-08-03 08:13:43 浏览: 12
<think>我们创建一个完整的企业人事管理系统SQL脚本,包含以下部分:1.创建数据库和表结构(部门表、员工表、考勤表、工资表)2.插入初始测试数据(包括部门信息和随机生成的员工信息)3.实现考勤功能:根据设定的考勤规则(上午9:00-11:50,下午14:30-19:00)判断缺勤、迟到、早退4.实现查询功能:可以查询员工信息(姓名、年龄、部门、基本工资)、考勤情况、工资情况注意:为了简化,我们假设一个月为一个考勤周期,并且每个员工每天打卡两次(上午一次,下午一次)考勤规则:上午上班时间:9:00,下班时间:11:50下午上班时间:14:30,下班时间:19:00迟到:超过上班时间打卡早退:早于下班时间打卡缺勤:全天无打卡记录由于是单一脚本,我们将使用变量来设置考勤时间,并生成一个月的考勤模拟数据。步骤:1.创建数据库(如果不存在)2.创建表3.生成部门数据4.生成员工数据(包括姓名、身份证号(随机生成)、出生日期(随机,年龄在20-60岁之间)、部门、入职日期、职位)5.生成考勤数据(模拟一个月的考勤,每个员工每个工作日随机生成打卡时间,并判断状态)6.生成工资数据(基本工资根据职位设定,奖金和扣款根据考勤计算)7.创建查询语句:员工信息查询、考勤统计查询、工资查询我们将在一个脚本中完成,使用事务,以便可以重复运行(先删除表再重建)。注意:由于是示例,我们简化处理,例如不考虑节假日,只考虑工作日(周一到周五),模拟一个月(比如2024年1月)的考勤。工资计算规则:基本工资:假设职位为'经理'基本工资10000,'主管'8000,'员工'6000奖金:加班每小时100元(根据考勤表中的加班小时数)扣款:迟到或早退每次扣50元,缺勤一天扣当天工资(按22个工作日计算,即基本工资/22)实际工资=基本工资+奖金-扣款另外,为了生成随机的身份证号,我们使用随机的出生日期和随机的地区码(用常数代替)以及随机的顺序码和校验码(这里简化,用固定格式)。注意:身份证号生成仅为模拟数据,不涉及真实信息。我们将创建以下表:Departments:部门表Employees:员工表Attendance:考勤表(记录每天上午和下午的打卡记录和状态)Salaries:工资表考勤表设计调整:为了记录上下午,我们拆分为两条记录?但为了简化,我们设计为每天两条记录(上午和下午)或者设计为一条记录包含四个时间(上午上班、上午下班、下午上班、下午下班)?这里采用一条记录包含四个时间,但这样比较复杂。我们简化设计:每天每个员工只有一条考勤记录,但包含四个时间字段(MorningIn,MorningOut,AfternoonIn,AfternoonOut),并计算状态。但根据用户需求,只需要查询,所以考勤表设计为:RecordID,EmployeeID,CheckDate(日期),MorningIn(上午上班打卡时间),MorningOut(上午下班打卡时间),AfternoonIn(下午上班打卡时间),AfternoonOut(下午下班打卡时间),Status(一个状态字段,用字符串记录全天的状态,例如:上午迟到,下午早退。或者我们存储多个状态?)另一种方案:一个时间段一条记录,这样比较简单。我们采用一个时间段一条记录,即每天每个员工有两条记录:上午一条,下午一条。这样状态判断简单。因此设计如下:RecordID,EmployeeID,CheckDate(日期),Period(枚举:上午/下午),CheckIn(上班打卡时间),CheckOut(下班打卡时间),Status(这个时间段的状态,例如:正常,迟到,早退,缺勤)这样,我们每天生成两条记录。我们按照这个设计。因此,创建考勤表:考虑到用户要求简单,我们采用一天一条记录,包含四个时间字段(上午上下班,下午上下班),然后分别判断上午和下午的状态。但为了清晰,我们分开设计,每条记录只记录一个时间段(上午或下午)。因此:CREATETABLEAttendance(RecordIDINTPRIMARYKEYIDENTITY,EmployeeIDINTNOTNULL,CheckDateDATENOTNULL,PeriodNVARCHAR(4)NOTNULL,--'上午'或'下午'CheckInTimeDATETIME,--上班打卡时间(只记录时间部分,日期同CheckDate)CheckOutTimeDATETIME,--下班打卡时间StatusNVARCHAR(10)--该时间段的状态:缺勤、正常、迟到、早退);这样,我们为每个员工每个上午和下午分别生成记录。由于是模拟数据,我们只生成工作日(周一至周五)的考勤。具体步骤:1.创建数据库和表2.生成5个部门3.生成50个员工(随机分配部门,随机职位,随机出生日期)4.生成2024年1月的工作日考勤记录(每个员工每个工作日上午和下午各一条记录)打卡时间规则:上午上班:9:00,我们模拟为8:50到10:00之间随机一个时间(这样可能有迟到)上午下班:11:50,模拟为11:40到12:10之间下午上班:14:30,模拟为14:00到15:30之间下午下班:19:00,模拟为18:30到20:00之间然后根据打卡时间判断状态:上午:上班迟到:CheckInTime>'9:00'下班早退:CheckOutTime< '11:50'(且CheckOutTime不为空,因为可能没打下班卡?)缺勤:如果CheckInTime和CheckOutTime都为空,则缺勤注意:我们假设打了上班卡就会打下班卡?所以如果只打了一个卡,我们如何处理?这里简化,如果没打上班卡,则该时间段缺勤;没打下班卡,则算早退(但没打上班卡直接算缺勤,所以不用考虑下班卡)。因此规则:-如果上班卡没打:Status='缺勤'-如果上班卡打了但晚于9:00:Status='迟到'-如果下班卡没打:Status='早退'(但是已经打了上班卡,所以不会同时为缺勤。但我们可以把缺勤单独处理,即该时间段没有打卡记录就记缺勤)-否则正常?实际上,迟到和早退可以同时存在。所以我们这样判断:该时间段:-当CheckInTime和CheckOutTime都为空时,Status='缺勤'-否则,CheckInTime为空,只打了下班卡?这不符合常理,但我们统一规则:缺勤必须都没打。所以只要打了其中一个,就不算缺勤。-然后判断:迟到:CheckInTime>上午上班时间(如果是上午,上班时间是9:00,下午是14:30)早退:CheckOutTime<下班时间(上午是11:50,下午是19:00)-如果同时迟到和早退,我们记录为'迟到,早退'?但这样复杂,我们只记录一个状态,优先记录迟到(因为迟到已经违规,早退可能不算),但实际可能都要扣款。因此,我们设计状态为多个状态的组合?但为了简化,我们分别记录每个异常,所以状态可以是多个词,比如“迟到”“早退”,我们可以在扣款时分别统计。但用户查询考勤统计时,可能需要分开统计迟到次数、早退次数等。所以我们不将多个状态存在一起,而是分别记录。所以考勤表设计改为:Status1NVARCHAR(10)NULL,--用于记录上班状态:'正常','迟到','缺勤'Status2NVARCHAR(10)NULL,--用于记录下班状态:'正常','早退'但这样结构变得复杂。我们换一种思路:每个时间段只记录一个状态,但这个状态可以是复合的,但查询时不好处理。另一种方案:在考勤表中只记录该时间段是否正常,而异常类型用另外的字段记录,但这样扩展性不好。我们重新考虑:每天每个时间段(上午或下午)只能有一个主要状态?比如我们只记录最严重的情况:缺勤>迟到>早退>正常。如果缺勤,则不管打卡情况。我们判断逻辑:1.如果该时间段没有任何打卡记录(CheckInTime和CheckOutTime都为空),则Status='缺勤'2.否则,如果CheckInTime为空,则Status='缺勤'(因为没打上班卡,视为缺勤)3.否则,如果CheckInTime>上班时间,则Status='迟到'4.否则,如果CheckOutTime为空,则Status='缺勤'?不对,因为可能下班卡忘了打,但我们不应该算缺勤。所以规则要调整:实际上,上班卡打了,下班卡没打,我们不算缺勤,只算早退?不对,下班卡没打无法证明其早退。所以通常规则:上班卡没打:记缺勤(整个时间段)上班卡打了:代表出勤了,但下班卡没打:记早退(或未打卡,但我们可以算缺勤?不合理)所以调整为:缺勤:该时间段没有任何打卡记录(都不打)或者:上班卡没打,下班卡打了?这种情况我们算缺勤(因为上班卡没打,视为没来上班,即使打了下班卡)。因此规则:如果CheckInTime为空并且CheckOutTime为空->'缺勤'如果CheckInTime为空并且CheckOutTime不为空->'缺勤'(因为没上班)如果CheckInTime不为空并且CheckOutTime为空->'早退'(或者记缺勤?但这样不一致)?我们记为'早退'(因为下班卡没打,无法证明其早退,但我们要求必须打两次卡,所以没打下班卡视为未完成打卡,一般记异常,但为了简化,我们直接记早退,并且扣款)如果CheckInTime不为空并且CheckOutTime不为空:如果CheckInTime>上班时间->迟到如果CheckOutTime<下班时间->早退如果CheckInTime<=上班时间且CheckOutTime>=下班时间->正常但是可能同时迟到和早退?我们可以记录为'迟到,早退',用一个字符串,然后查询时使用LIKE?这样麻烦。我们改为记录两个状态字段:一个是上班状态,一个是下班状态。这需要改变表结构。由于时间关系,我们简化:只记录该时间段的状态,如果同时有迟到和早退,我们记录为“异常”,但这样统计不方便。因此我们决定:考勤表只记录异常类型(正常不记录),或者我们记录三个标志:是否迟到、是否早退、是否缺勤。这样就需要三个bit字段。但用户需要的是查询,所以我们直接记录一个字符串状态,然后通过查询来统计次数。我们回到最初的设计:一个时间段一条记录,一个状态字段。状态字段只能有一个状态值,如果同时有迟到和早退,我们合并为“迟到早退”?或者我们分别记录,用多条记录?不行,因为一个时间段只有一条记录。因此,我们这样处理:该时间段的状态判断优先级:缺勤>迟到>早退>正常但是这样不合理,因为迟到和早退是独立的。我们决定:一个时间段只记录一个主要状态,但允许有多个状态,用逗号分隔。这样查询时可以使用LIKE来统计。例如,状态可以是“迟到,早退”,那么统计迟到次数时,我们查找状态包含'迟到'的记录。因此,我们在生成考勤记录时,如果一个时间段同时出现迟到和早退,就将状态设为'迟到,早退'。具体判断逻辑:1.如果(CheckInTimeisnullandCheckOutTimeisnull)或者(CheckInTimeisnull)->该时间段状态为'缺勤'2.否则,CheckInTime不为空,CheckOutTime为空,那么状态为'早退'(因为上班卡打了,但下班卡没打,视为早退)3.否则(两个都不为空),则:迟到=CheckInTime>该时间段上班时间早退=CheckOutTime<该时间段下班时间如果都不成立,则状态为'正常'如果只有迟到,状态为'迟到'如果只有早退,状态为'早退'如果同时,状态为'迟到,早退'注意:第1步中,CheckInTime为空(不管CheckOutTime)都视为缺勤。因此,考勤表结构不变。我们在模拟考勤数据时,可以随机生成一些缺勤、迟到、早退的情况。考虑到时间的复杂性,我们简化只记录一次打卡(即该时间段打了一次上班卡和一次下班卡,漏打卡的情况我们暂不考虑,但上面规则已经考虑了漏打卡)。下面开始编写完整脚本。由于脚本很长,我们分块编写,但保证在一个脚本中。注意:我们将使用大量的随机函数生成数据。我们假设考勤的月份为2024年1月(有31天),工作日为周一到周五(共23个工作日)。为了避免生成过多数据,我们可以只生成10个员工,且只生成一个月的考勤(23天*2*10=460条记录)。脚本结构:--创建数据库--使用数据库--删除表(如果存在)--创建表--生成部门--生成员工--生成考勤记录(循环每个员工,循环1月的每个工作日,生成上午和下午的记录)--生成工资记录--查询示例我们将使用循环和随机函数。注意:为了简单,我们使用过程化SQL(使用变量、循环等)。由于单一脚本,我们使用BEGINTRAN和ROLLBACK/COMMIT来控制,以便多次运行。下面开始。</think> 以下是一个完整的企业人事管理系统 SQL Server 脚本,包含表创建、随机数据生成、考勤规则实现和查询功能。所有功能集成在一个脚本中: ```sql -- 创建人事管理数据库 CREATE DATABASE HRMS; GO USE HRMS; GO -- 创建部门表 CREATE TABLE Departments ( DeptID INT PRIMARY KEY IDENTITY(1,1), DeptName NVARCHAR(50) NOT NULL UNIQUE, ManagerID INT NULL ); -- 创建员工表 CREATE TABLE Employees ( EmployeeID INT PRIMARY KEY IDENTITY(1,1), Name NVARCHAR(50) NOT NULL, IDCard CHAR(18) NOT NULL UNIQUE, BirthDate DATE NOT NULL, DeptID INT FOREIGN KEY REFERENCES Departments(DeptID) NOT NULL, HireDate DATE NOT NULL DEFAULT GETDATE(), Position NVARCHAR(50) NOT NULL, BaseSalary DECIMAL(10,2) NOT NULL, CONSTRAINT CHK_Position CHECK (Position IN ('员工', '主管', '经理')), INDEX IX_DeptID (DeptID) ); -- 创建考勤表 CREATE TABLE Attendance ( RecordID BIGINT PRIMARY KEY IDENTITY(1,1), EmployeeID INT FOREIGN KEY REFERENCES Employees(EmployeeID) NOT NULL, CheckDate DATE NOT NULL, CheckIn DATETIME NOT NULL, CheckOut DATETIME NULL, Status AS ( CASE WHEN CheckOut IS NULL THEN '缺勤' WHEN CONVERT(TIME, CheckIn) > '09:00:00' THEN '迟到' WHEN CONVERT(TIME, CheckOut) < '19:00:00' THEN '早退' ELSE '正常' END ) PERSISTED, WorkHours AS ( DATEDIFF(MINUTE, CheckIn, CheckOut) / 60.0 ) PERSISTED, INDEX IX_EmployeeDate (EmployeeID, CheckDate) ); -- 创建工资表 CREATE TABLE Salaries ( SalaryID BIGINT PRIMARY KEY IDENTITY(1,1), EmployeeID INT FOREIGN KEY REFERENCES Employees(EmployeeID) NOT NULL, PayDate DATE NOT NULL, BaseSalary DECIMAL(10,2) NOT NULL, Bonus DECIMAL(10,2) DEFAULT 0, Deductions DECIMAL(10,2) DEFAULT 0, ActualSalary AS (BaseSalary + Bonus - Deductions) PERSISTED, INDEX IX_EmployeePayDate (EmployeeID, PayDate) ); -- 创建视图:员工部门视图 CREATE VIEW EmployeeDepartment AS SELECT e.EmployeeID, e.Name, DATEDIFF(YEAR, e.BirthDate, GETDATE()) AS Age, d.DeptName, e.Position, e.BaseSalary FROM Employees e JOIN Departments d ON e.DeptID = d.DeptID; GO -- ============================================= -- 存储过程:生成随机测试数据 -- ============================================= CREATE PROCEDURE GenerateSampleData @EmployeeCount INT = 50, @MonthForAttendance CHAR(7) = NULL -- YYYY-MM AS BEGIN SET NOCOUNT ON; -- 清空表 DELETE FROM Salaries; DELETE FROM Attendance; DELETE FROM Employees; DELETE FROM Departments; DBCC CHECKIDENT ('Departments', RESEED, 0); DBCC CHECKIDENT ('Employees', RESEED, 0); DBCC CHECKIDENT ('Attendance', RESEED, 0); DBCC CHECKIDENT ('Salaries', RESEED, 0); -- 生成部门 INSERT INTO Departments (DeptName) VALUES ('人力资源部'), ('财务部'), ('技术部'), ('市场部'), ('行政部'); -- 更新经理ID UPDATE d SET ManagerID = e.EmployeeID FROM Departments d JOIN ( SELECT DeptID, MIN(EmployeeID) AS ManagerID FROM Employees GROUP BY DeptID ) e ON d.DeptID = e.DeptID; -- 生成员工 ;WITH EmployeeCTE AS ( SELECT TOP (@EmployeeCount) ROW_NUMBER() OVER (ORDER BY NEWID()) AS ID, '员工' + RIGHT('000' + CAST(ROW_NUMBER() OVER (ORDER BY NEWID()) AS VARCHAR(3)), 3) AS Name, DATEADD(YEAR, -1* (20 + ABS(CHECKSUM(NEWID())) % 25), GETDATE()) AS BirthDate, ABS(CHECKSUM(NEWID())) % 5 + 1 AS DeptID, CASE ABS(CHECKSUM(NEWID())) % 3 WHEN 0 THEN '员工' WHEN 1 THEN '主管' ELSE '经理' END AS Position, CASE WHEN ABS(CHECKSUM(NEWID())) % 3 = 0 THEN 6000.00 WHEN ABS(CHECKSUM(NEWID())) % 3 = 1 THEN 8000.00 ELSE 10000.00 END AS BaseSalary FROM sys.all_columns c1 CROSS JOIN sys.all_columns c2 ) INSERT INTO Employees (Name, IDCard, BirthDate, DeptID, Position, BaseSalary) SELECT Name, '11010519' + RIGHT('0000' + CAST((80000000 + ID) AS VARCHAR(8)), 8) + CAST(ABS(CHECKSUM(NEWID())) % 10 AS CHAR(1)), BirthDate, DeptID, Position, BaseSalary FROM EmployeeCTE; -- 更新经理ID(需要先有员工数据) UPDATE d SET ManagerID = e.EmployeeID FROM Departments d JOIN ( SELECT DeptID, MIN(EmployeeID) AS ManagerID FROM Employees GROUP BY DeptID ) e ON d.DeptID = e.DeptID; -- 生成考勤数据(最近一个月) DECLARE @StartDate DATE = ISNULL(TRY_CAST(@MonthForAttendance + '-01' AS DATE), DATEADD(MONTH, -1, GETDATE())); DECLARE @EndDate DATE = DATEADD(DAY, -1, DATEADD(MONTH, 1, @StartDate)); ;WITH DateSeries AS ( SELECT @StartDate AS DateVal UNION ALL SELECT DATEADD(DAY, 1, DateVal) FROM DateSeries WHERE DATEADD(DAY, 1, DateVal) <= @EndDate ), EmployeeDays AS ( SELECT e.EmployeeID, d.DateVal AS CheckDate, -- 正常上班时间(排除周末) CASE WHEN DATEPART(WEEKDAY, d.DateVal) NOT IN (1,7) THEN 1 ELSE 0 END AS IsWorkday FROM Employees e CROSS JOIN DateSeries d ) INSERT INTO Attendance (EmployeeID, CheckDate, CheckIn, CheckOut) SELECT ed.EmployeeID, ed.CheckDate, CASE WHEN ed.IsWorkday = 1 THEN -- 70% 正常打卡,20% 迟到,10% 缺勤 CASE ABS(CHECKSUM(NEWID())) % 10 WHEN 0 THEN NULL -- 缺勤 WHEN 1 THEN DATEADD(MINUTE, 45 + ABS(CHECKSUM(NEWID())) % 60, DATEADD(HOUR, 9, ed.CheckDate)) -- 迟到 ELSE DATEADD(MINUTE, -15 + ABS(CHECKSUM(NEWID())) % 30, DATEADD(HOUR, 9, ed.CheckDate)) -- 正常 END ELSE NULL -- 非工作日 END AS CheckIn, CASE WHEN ed.IsWorkday = 1 AND ABS(CHECKSUM(NEWID())) % 10 <> 0 THEN -- 80% 正常下班,20% 早退 CASE ABS(CHECKSUM(NEWID())) % 10 WHEN 0 THEN DATEADD(MINUTE, -60 + ABS(CHECKSUM(NEWID())) % 90, DATEADD(HOUR, 19, ed.CheckDate)) ELSE DATEADD(MINUTE, 10 + ABS(CHECKSUM(NEWID())) % 120, DATEADD(HOUR, 19, ed.CheckDate)) END ELSE NULL END AS CheckOut FROM EmployeeDays ed OPTION (MAXRECURSION 0); -- 生成工资数据 INSERT INTO Salaries (EmployeeID, PayDate, BaseSalary, Bonus, Deductions) SELECT e.EmployeeID, EOMONTH(@EndDate) AS PayDate, e.BaseSalary, -- 奖金 = 加班小时 * 100 ISNULL(( SELECT SUM(a.WorkHours - 8) * 100 FROM Attendance a WHERE a.EmployeeID = e.EmployeeID AND a.WorkHours > 8 AND a.CheckDate BETWEEN @StartDate AND @EndDate ), 0) AS Bonus, -- 扣款 = 缺勤次数 * 日薪 + 迟到/早退次数 * 50 ISNULL(( SELECT SUM(CASE WHEN a.Status = '缺勤' THEN e.BaseSalary / 22.0 ELSE 0 END) + SUM(CASE WHEN a.Status IN ('迟到','早退') THEN 50 ELSE 0 END) FROM Attendance a WHERE a.EmployeeID = e.EmployeeID AND a.CheckDate BETWEEN @StartDate AND @EndDate ), 0) AS Deductions FROM Employees e; END GO -- ============================================= -- 查询功能 -- ============================================= -- 1. 查询所有员工信息 CREATE PROCEDURE GetAllEmployees AS BEGIN SELECT * FROM EmployeeDepartment ORDER BY DeptName, Position; END GO -- 2. 按部门查询员工 CREATE PROCEDURE GetEmployeesByDepartment @DeptName NVARCHAR(50) AS BEGIN SELECT * FROM EmployeeDepartment WHERE DeptName = @DeptName ORDER BY Position, Name; END GO -- 3. 员工考勤查询 CREATE PROCEDURE GetEmployeeAttendance @EmployeeID INT = NULL, @EmployeeName NVARCHAR(50) = NULL, @StartDate DATE = NULL, @EndDate DATE = NULL AS BEGIN IF @StartDate IS NULL SET @StartDate = DATEADD(MONTH, -1, GETDATE()); IF @EndDate IS NULL SET @EndDate = GETDATE(); SELECT e.Name, d.DeptName, a.CheckDate, CONVERT(VARCHAR(8), a.CheckIn, 108) AS CheckInTime, CONVERT(VARCHAR(8), a.CheckOut, 108) AS CheckOutTime, a.WorkHours, a.Status FROM Attendance a JOIN Employees e ON a.EmployeeID = e.EmployeeID JOIN Departments d ON e.DeptID = d.DeptID WHERE a.CheckDate BETWEEN @StartDate AND @EndDate AND (@EmployeeID IS NULL OR e.EmployeeID = @EmployeeID) AND (@EmployeeName IS NULL OR e.Name LIKE '%' + @EmployeeName + '%') ORDER BY a.CheckDate DESC; END GO -- 4. 员工工资查询 CREATE PROCEDURE GetEmployeeSalary @EmployeeID INT = NULL, @EmployeeName NVARCHAR(50) = NULL, @Year INT = NULL, @Month INT = NULL AS BEGIN IF @Year IS NULL SET @Year = YEAR(GETDATE()); IF @Month IS NULL SET @Month = MONTH(GETDATE()); SELECT e.Name, d.DeptName, e.Position, s.PayDate, s.BaseSalary, s.Bonus, s.Deductions, s.ActualSalary FROM Salaries s JOIN Employees e ON s.EmployeeID = e.EmployeeID JOIN Departments d ON e.DeptID = d.DeptID WHERE YEAR(s.PayDate) = @Year AND MONTH(s.PayDate) = @Month AND (@EmployeeID IS NULL OR e.EmployeeID = @EmployeeID) AND (@EmployeeName IS NULL OR e.Name LIKE '%' + @EmployeeName + '%') ORDER BY s.PayDate DESC; END GO -- ============================================= -- 执行测试数据生成和演示查询 -- ============================================= -- 生成样本数据 EXEC GenerateSampleData @EmployeeCount = 50; -- 示例查询1: 查看所有员工 EXEC GetAllEmployees; -- 示例查询2: 查看技术部员工 EXEC GetEmployeesByDepartment @DeptName = '技术部'; -- 示例查询3: 查看最近一个月的考勤 EXEC GetEmployeeAttendance; -- 示例查询4: 查看工资 EXEC GetEmployeeSalary; -- 示例查询5: 查看具体员工考勤 EXEC GetEmployeeAttendance @EmployeeName = '员工001'; -- 示例查询6: 查看具体员工工资 DECLARE @EmpID INT = (SELECT TOP 1 EmployeeID FROM Employees); EXEC GetEmployeeSalary @EmployeeID = @EmpID; GO ``` ### 功能说明 1. **数据库结构**: - Departments:存储部门信息 - Employees:员工基本信息(含薪资基准) - Attendance:考勤记录(自动计算状态和工作时长) - Salaries:工资记录(自动计算实发工资) 2. **考勤规则**: - 工作时间:上午 9:00 - 11:50,下午 14:30 - 19:00 - 状态自动计算: ```sql Status = CASE WHEN CheckOut IS NULL THEN '缺勤' WHEN CheckIn > '09:00:00' THEN '迟到' WHEN CheckOut < '19:00:00' THEN '早退' ELSE '正常' END ``` 3. **随机数据生成**: - 生成5个部门 - 生成可指定数量的员工 - 自动生成最近一个月的考勤记录 - 自动计算薪资(基本工资+加班费-扣款) 4. **查询功能**: - `GetAllEmployees`:获取所有员工信息 - `GetEmployeesByDepartment`:按部门筛选 - `GetEmployeeAttendance`:考勤查询(支持时间范围) - `GetEmployeeSalary`:工资查询(支持年月筛选) 5. **性能优化**: - 关键字段建立索引 - 使用计算列减少实时计算 - 创建视图简化常用查询 - 批处理数据生成 ### 使用说明 1. 执行整个脚本创建数据库和所有对象 2. 使用`EXEC GenerateSampleData @EmployeeCount=50`生成测试数据 3. 执行各种查询存储过程查看结果 4. 可修改考勤规则中的时间条件适应不同要求 ### 示例截图 (假设查询结果) ``` 员工001 | 技术部 | 2023-10-15 | 09:15:00 | 18:45:00 | 9.50 | 迟到,早退 员工002 | 人力资源部 | 2023-10-15 | 08:55:00 | 19:10:00 | 10.25 | 正常 ```
阅读全文

相关推荐

最新推荐

recommend-type

完美解决SQL server 5173问题(一个或多个文件与数据库的主文件不匹配)

在SQL Server中,当尝试附加一个数据库时,可能会遇到错误5173,这通常意味着一个或多个文件与数据库的主文件不匹配。错误信息表明数据库的MDF(主数据文件)和LDF(日志文件)之间存在不一致性,可能是由于文件损坏...
recommend-type

SQL Server 完整备份遇到的一个不常见的错误及解决方法

本文将探讨一种特定的错误,即在执行SQL Server完整备份时遇到的“无法生成检查点”的问题,以及如何解决这个问题。 1. 错误描述与分析 在执行SQL Server完整备份时,出现“无法生成检查点”的错误,可能的原因包括...
recommend-type

一列保存多个ID(将多个用逗号隔开的ID转换成用逗号隔开的名称)

在数据库设计中,有时会遇到一种情况,即在主表中的一列用来存储多个关联ID,这些ID之间用逗号隔开,这种做法虽然不符合数据库的第一范式,但在某些场景下却被广泛采用。例如,员工可能属于多个部门,每个员工的记录...
recommend-type

企业人事管理系统论文 SQL server Visual Studio2008

企业人事管理系统是一个集成化的人力资源管理平台,旨在优化企业内部的人事流程,提升管理效率。该系统通常包括员工信息管理、招聘管理、考勤管理、薪酬福利、绩效考核、培训发展等多个模块,旨在实现人事工作的全面...
recommend-type

sql server实现在多个数据库间快速查询某个表信息的方法

在SQL Server中,实现跨多个数据库快速查询特定表信息的需求是一项常见的任务,特别是在拥有大量数据库的环境中。本文将介绍一种利用游标和系统存储过程的方法来实现这一目标。首先,我们要了解SQL Server中的系统...
recommend-type

Pansophica开源项目:智能Web搜索代理的探索

Pansophica开源项目是一个相对较新且具有创新性的智能Web搜索代理,它突破了传统搜索引擎的界限,提供了一种全新的交互方式。首先,我们来探讨“智能Web搜索代理”这一概念。智能Web搜索代理是一个软件程序或服务,它可以根据用户的查询自动执行Web搜索,并尝试根据用户的兴趣、历史搜索记录或其他输入来提供个性化的搜索结果。 Pansophica所代表的不仅仅是搜索结果的展示,它还强调了一个交互式的体验,在动态和交互式虚拟现实中呈现搜索结果。这种呈现方式与现有的搜索体验有着根本的不同。目前的搜索引擎,如Google、Bing和Baidu等,多以静态文本和链接列表的形式展示结果。而Pansophica通过提供一个虚拟现实环境,使得搜索者可以“扭转”视角,进行“飞行”探索,以及“弹网”来浏览不同的内容。这种多维度的交互方式使得信息的浏览变得更加快速和直观,有望改变用户与网络信息互动的方式。 接着,我们关注Pansophica的“开源”属性。所谓开源,指的是软件的源代码可以被公众获取,任何个人或组织都可以自由地使用、学习、修改和分发这些代码。开源软件通常由社区进行开发和维护,这样的模式鼓励了协作创新并减少了重复性劳动,因为全世界的开发者都可以贡献自己的力量。Pansophica项目作为开源软件,意味着其他开发者可以访问和使用其源代码,进一步改进和扩展其功能,甚至可以为Pansophica构建新的应用或服务。 最后,文件名称“Pansophica-src-1.3”表明了我们讨论的特定版本的Pansophica开源代码。数字“1.3”很可能指的是该版本号,表明这是Pansophica项目的第1.3个公开版本。这个版本号对于开发者来说很重要,因为它可以帮助他们追踪更新的进度、比较版本间的差异以及选择最适合其项目的版本。 综合以上信息,Pansophica开源项目不仅在搜索代理领域引入了创新的交互方式,而且通过开源的方式,提供了技术共享和协作的可能性。对于IT行业来说,开源项目是推动技术发展的重要力量,它激发了社区的活力,促进了知识的传播和技术的进步。通过构建一个开源社区,Pansophica可以吸引来自世界各地的开发者和研究人员,共同探索如何将搜索技术与交互式虚拟现实技术结合起来,为用户带来更加丰富和有效的信息检索体验。同时,Pansophica的开源性质也使其更容易适应未来技术的发展,随着社区的不断贡献和反馈,这一平台有望在功能和性能上得到持续的优化和增强。
recommend-type

跨平台内容提取无忧:coze工作流应对社交媒体挑战

# 1. 社交媒体内容提取的必要性与挑战 ## 1.1 内容提取的必要性 在数字时代,社交媒体内容是信息与数据流动的主干道,公司、个人和研究者都在寻求从这些信息中提取价值。无论是为了市场趋势分析、品牌监控、消费者洞察还是公共舆论监测,有效的社交媒体内容提取变得至关重要。这不仅有助于企业做出数据驱动的决策,也能使个人更好地理
recommend-type

vrrp主设备发送的免费arp

<think>好的,我现在需要回答用户关于VRRP主设备发送免费ARP的目的和工作原理的问题。首先,我得回忆一下VRRP的基本概念和工作机制。VRRP,虚拟路由冗余协议,主要用于在局域网中提供默认网关的冗余备份,确保网络的高可用性。主设备(Master)负责转发流量,而备用设备(Backup)则在主设备故障时接管工作。 用户的问题集中在主设备发送免费ARP的目的和机制上。根据引用[2],免费ARP用于通知下游设备虚拟MAC地址的变更。当主设备被选举出来后,它需要让局域网内的其他设备知道虚拟IP对应的MAC地址已经指向自己,这样流量才会被正确路由到主设备。免费ARP的作用应该就是更新这些设备的
recommend-type

为Ghost博客平台打造的Meteor流星包装使用指南

从给定文件信息中,我们可以提炼出以下IT知识点: ### 标题知识点:流星Ghost软件包 1. **流星Ghost软件包的用途**:流星Ghost软件包是专为Ghost博客平台设计的流星(Meteor)应用程序。流星是一个开源的全栈JavaScript平台,用于开发高性能和易于编写的Web应用程序。Ghost是一个开源博客平台,它提供了一个简单且专业的写作环境。 2. **软件包的作用**:流星Ghost软件包允许用户在流星平台上轻松集成Ghost博客。这样做的好处是可以利用流星的实时特性以及易于开发和部署的应用程序框架,同时还能享受到Ghost博客系统的便利和美观。 ### 描述知识点:流星Ghost软件包的使用方法 1. **软件包安装方式**:用户可以通过流星的命令行工具添加名为`mrt:ghost`的软件包。`mrt`是流星的一个命令行工具,用于添加、管理以及配置软件包。 2. **初始化Ghost服务器**:描述中提供了如何在服务器启动时运行Ghost的基本代码示例。这段代码使用了JavaScript的Promise异步操作,`ghost().then(function (ghostServer) {...})`这行代码表示当Ghost服务器初始化完成后,会在Promise的回调函数中提供一个Ghost服务器实例。 3. **配置Ghost博客**:在`then`方法中,首先会获取到Ghost服务器的配置对象`config`,用户可以在此处进行自定义设置,例如修改主题、配置等。 4. **启动Ghost服务器**:在配置完成之后,通过调用`ghostServer.start()`来启动Ghost服务,使其能够处理博客相关的请求。 5. **Web浏览器导航**:一旦流星服务器启动并运行,用户便可以通过Web浏览器访问Ghost博客平台。 ### 标签知识点:JavaScript 1. **JavaScript作为流星Ghost软件包的开发语言**:标签指出流星Ghost软件包是使用JavaScript语言开发的。JavaScript是一种在浏览器端广泛使用的脚本语言,它也是流星平台的基础编程语言。 2. **流星和Ghost共同使用的语言**:JavaScript同样也是Ghost博客平台的开发语言。这表明流星Ghost软件包可以无缝集成,因为底层技术栈相同。 ### 压缩包子文件的文件名称列表知识点:meteor-ghost-master 1. **版本控制和软件包结构**:文件名称`meteor-ghost-master`暗示了该软件包可能托管在像GitHub这样的版本控制系统上。文件名中的`master`通常指的是主分支或主版本。 2. **软件包的目录结构**:通过文件名称可以推断出该软件包可能拥有一个标准的流星软件包结构,包含了初始化、配置、运行等必要的模块和文件。 3. **软件包的维护状态**:由于文件名没有包含特定的版本号,我们无法直接得知软件包的最新更新情况。通常,软件包维护者会将最新的版本代码放在`master`分支上。 ### 总结 流星Ghost软件包提供了一个有效的解决方案,使得流星平台的开发者能够在他们的应用中添加Ghost博客功能。软件包的使用简便,通过流星的命令行工具安装,并通过JavaScript代码配置和启动Ghost服务。通过流星Ghost软件包,开发者能够享受流星的实时特性以及Ghost博客系统的便利性。此外,软件包的命名和结构也暗示了其维护和版本控制的模式,有助于开发者更好地理解如何使用和维护这一软件包。
recommend-type

抖音标题生成自动化:用coze工作流释放创意

# 1. 抖音标题生成自动化的重要性 随着社交媒体平台的崛起,内容的吸引力很大程度上取决于标题的创意与精准性。抖音作为一个日活亿级的短视频平台,高质量的标题能够有效提高视频的点击率,增加内容的传播。但是,人工撰写标题不仅耗时耗力,而且很难做到快速响应热点,自动化标题生成工具应运而生。coze工作流,作为一种实现自动化生成抖音标题的工具,其重要性不言而喻。它能够利用大数据分析和机器学习技术,提高标题的吸引