背景:我有一个表,该表包含一个人的列表,另一个表用于发生的事件。我需要一个事件的发生日期,该事件最后发生在一个人的数据库列中。
所以我的理解是,我需要使用SQL Server代理创建并运行一个存储过程,该存储过程将为我执行此操作。不过,我从未编写过存储过程,因此这对我也是一种实践。
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Gary Senter
-- Create date: 5/25/2019
-- Description: Returns employee data.
-- =============================================
ALTER PROCEDURE [dbo].[spLocal_Safety_Sync]
@LastName NVARCHAR(50) = NULL,
@FirstName NVARCHAR(50) = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE @injury_date DATETIME;
DECLARE @short_name_1 VARCHAR(50);
DECLARE @short_name_2 VARCHAR(50);
DECLARE @short_name_3 VARCHAR(50);
DECLARE @cc_roster_id_emp_1 INT;
DECLARE @cc_roster_id_emp_2 INT;
DECLARE @cc_roster_id_emp_3 INT;
SELECT
@short_name_1 = effected_employee_1,
@short_name_2 = effected_employee_2,
@short_name_3 = effected_employee_3,
@injury_date = IncidentDate
FROM
HSEBE.dbo.MCA_Data
WHERE
(Classification = 'XX RI' OR Classification = 'YY RI')
ORDER BY
IncidentDate ASC
IF LEN(@short_name_1) > 0
THEN
SELECT @cc_roster_id_emp_1 = autoid
FROM cc_rosters
WHERE short_name = @short_name_1
IF LEN(@short_name_2) > 0
THEN
SELECT @cc_roster_id_emp_2 = autoid
FROM cc_rosters
WHERE short_name = @short_name_2
IF LEN(@short_name_3) > 0
THEN
SELECT @cc_roster_id_emp_3 = autoid
FROM cc_rosters
WHERE short_name = @short_name_3
IF @cc_roster_id_emp_1 > 0
THEN
UPDATE cc_rosters
SET most_recent_injury = @injury_date
WHERE autoid = @short_name_1
IF @cc_roster_id_emp_2 > 0
THEN
UPDATE cc_rosters
SET most_recent_injury = @injury_date
WHERE autoid = @short_name_2
IF @cc_roster_id_emp_3 > 0
THEN
UPDATE cc_rosters
SET most_recent_injury = @injury_date
WHERE autoid = @short_name_3
END
我得到这些错误:
消息156,级别15,状态1,过程spLocal_Safety_Sync,第28行
关键字“ THEN”附近的语法不正确。消息156,级别15,状态1,过程spLocal_Safety_Sync,第30行
关键字“ THEN”附近的语法不正确。消息156,级别15,状态1,过程spLocal_Safety_Sync,第32行
关键字“ THEN”附近的语法不正确。消息156,级别15,状态1,过程spLocal_Safety_Sync,第35行
关键字“ then”附近的语法错误。消息156,级别15,状态1,过程spLocal_Safety_Sync,第37行
关键字“ then”附近的语法错误。消息156,级别15,状态1,过程spLocal_Safety_Sync,第39行
关键字'then'附近的语法不正确。
不确定从何处转向。...
并不总是有effected_employee_1,2,3,有时选定的值不会从其他数据库返回。
答案 0 :(得分:0)
好吧,这有点多了,我了解您仍在学习,所以让我向您展示我将如何处理。另外,将其与盐b / c混合使用,我对数据或预期的输出没有可见性。我认为,这将使您到达那里。但不利的是,它每次都会为每个员工更新。您可以更改以检查匹配项并轻松排除匹配项,但这比其他任何事情都更重要。
首先让我解释一下我在这里看到的问题:
看起来您的MCA_Data表中的数据结构错误。我的意思是说它是一个“扁平”表,其中有多名员工排成一排。通常,它是在多对一情况下执行检查数据任务时使用的PITA。通常,会有一个表,其中每个事件记录分别记录有事件ID和employeeID的每个人。我了解您可能没有构建它,但是值得为您指出自己的信息。
从根本上讲,一旦您理解了这个不那么理想的结构如何影响您的任务,这个问题就更容易解决。在我看来,这本质上是一个关键问题。 SQL中的PIVOT本质上是在切换行和列。如果要查找每个员工的最大事件发生日期,我们只需要更改MCA_Data表中的数据即可进行处理,对吗?有几种方法可以用代码来透视数据-选择您喜欢的-大多数人实际上都使用PIVOT函数,在这里我倾向于在CTE(常见表经验)和PIVOT之间摇摆不定。一旦了解IMO CTE,就更易于阅读。运行此代码,看看是否返回正确的结果。
; WITH CTE AS
(
SELECT Employee, AutoID, MAX(IncidentDate) AS MaxIncidentDate
FROM
(
SELECT
effected_employee_1 AS Employee,
cc1.autoID AS AutoID,
MAX(IncidentDate) AS IncidentDate
FROM
HSEBE.dbo.MCA_Data mca
LEFT JOIN
cc_rosters cc1 ON mac. effected_employee_1 = cc1. short_name
WHERE
(Classification = 'XX RI' OR Classification = 'YY RI')
AND effected_employee_1 IS NOT NULL
GROUP BY
effected_employee_1,
cc1.autoID
UNION
SELECT
effected_employee_2 AS Employee,
cc2.AutoID AS AutoID,
MAX(IncidentDate) AS IncidentDate
FROM
HSEBE.dbo.MCA_Data mca
LEFT JOIN
cc_rosters cc2 ON mac. effected_employee_2 = cc2. short_name
WHERE
(Classification = 'XX RI' OR Classification = 'YY RI')
AND effected_employee_2 IS NOT NULL
GROUP BY
effected_employee_2,
cc2.autoID
UNION
SELECT
effected_employee_3 AS Employee,
cc3.autoID AS AutoID,
MAX(IncidentDate) AS IncidentDate
FROM
HSEBE.dbo.MCA_Data mca
LEFT JOIN
cc_rosters cc3 ON mac. effected_employee_3 = cc3. short_name
WHERE
(Classification = 'XX RI' OR Classification = 'YY RI')
AND effected_employee_3 IS NOT NULL
GROUP BY
effected_employee_3,
cc3.autoID
) x
GROUP BY
Employee, AutoID,
)
SELECT * FROM CTE
现在,您为列中不为空的每个员工确定了最大事件发生日期之后,只需在此处进行更新即可。通过联接进行更新是您要擅长的事情。防止所有这些IF和变量以及各种语句。这也可以帮助您以基于集合的方式进行操作。在继续学习的过程中,您将不断听到。我建议您理解它!
; WITH CTE AS
(
SELECT Employee, AutoID, MAX(IncidentDate) AS MaxIncidentDate
FROM
(
SELECT
effected_employee_1 AS Employee,
cc1.autoID AS AutoID,
MAX(IncidentDate) AS IncidentDate
FROM
HSEBE.dbo.MCA_Data mca
LEFT JOIN
cc_rosters cc1 ON mac. effected_employee_1 = cc1. short_name
WHERE
(Classification = 'XX RI' OR Classification = 'YY RI')
AND effected_employee_1 IS NOT NULL
GROUP BY
effected_employee_1,
cc1.autoID
UNION
SELECT
effected_employee_2 AS Employee,
cc2.AutoID AS AutoID,
MAX(IncidentDate) AS IncidentDate
FROM
HSEBE.dbo.MCA_Data mca
LEFT JOIN
cc_rosters cc2 ON mac. effected_employee_2 = cc2. short_name
WHERE
(Classification = 'XX RI' OR Classification = 'YY RI')
AND effected_employee_2 IS NOT NULL
GROUP BY
effected_employee_2,
cc2.autoID
UNION
SELECT
effected_employee_3 AS Employee,
cc3.autoID AS AutoID,
MAX(IncidentDate) AS IncidentDate
FROM
HSEBE.dbo.MCA_Data mca
LEFT JOIN
cc_rosters cc3 ON mac. effected_employee_3 = cc3. short_name
WHERE
(Classification = 'XX RI' OR Classification = 'YY RI')
AND effected_employee_3 IS NOT NULL
GROUP BY
effected_employee_3,
cc3.autoID
) x
GROUP BY
Employee, AutoID,
)
UPDATE r SET r.most_recent_injury = cte.MaxIncidentDate
FROM cc_rosters r
INNER JOIN CTE ON r.AutoID = CTE.AutoID AND r.short_name =cte.Employee;
在具有多个命令的过程中,习惯于使用';'。字符以终止每一行。这是一个好习惯。