存储过程中的临时 Table 返回与常规查询不同的值
Temporary Table in Stored Procedure is returning different values than in regular query
所以。奇怪的情况。我在与之交互的数据库中有一个用户 table。它看起来像这样:
EXTENSIONID USERID FIRSTNAME EXTENSION ts
448980 4389116109 Johnny Gorman 51980 2019-07-15 03:00:24
683597 4389116109 James Sutherland 51980 2019-08-08 14:32:00
683598 4399610820 Sara Sarason 51802 2019-08-12 15:38:21
683599 4389116109 James Sutherland 51980 2019-08-12 16:32:32
基本上,USERID 是我们员工计时 table 的外键,而且有问题的是,它 不是 对一个用户唯一的:如果我们不授予一个新用户一个新的 USERID 当我们为他们分配他们的 EXTENSION 时,他们将接管该 EXTENSION 的最后持有者的 USERID(正如你在上面看到的 Johnny Gorman 和 James Sutherland 所发生的那样)。
此外,正如您在 James Sutherland 身上看到的那样,一个特定的用户可以有多个具有相同 USERID 的行。 EXTENSIONID 是 table 的主键,它 是 唯一的,但它是另一组 table 的外键。
table 的时间戳字段最后有用。因此,换句话说,时间戳将小于或等于该时间戳的所有内容都属于该行,直到先前的时间戳。
换句话说,为了让我的用户 table 附加到我的计时数据,我过去必须根据时间戳执行相关子查询,如下所示:
select * from timekeeping_tables as tt
inner join USERS as u on tt.USERID = u.USERID
and u.ts = (select max(ts) from USERS where ts <= tt.ENDTIME and USERID = u.USERID)
除了速度之外,这在所有方面都工作得很好:对如此大的数据集进行相关子查询需要很长时间。因此,相反,我想出了一种方法来为 USERS table 中的每一行创建一个有效日期和无效日期列表,这样加入将是对 USERID 和 [ 之间的一个简单的相等匹配=48=] 子句在 Effective/Ineffective 日期上。它看起来像这样:
select
mx.FIRSTNAME as 'Name',
mx.EXTENSION as 'Extension',
mx.USERID,
min(mx.Start_Time) as 'AGP_Start_Date',
max(mx.End_Time) as 'AGP_End_Date'
from (
select
m3.FIRSTNAME,
m3.EXTENSION,
m3.Start_Time,
case
when @lastUSER <> m3.USERID
then subdate(adddate(curdate(),interval 1 day), interval 1 second)
else m3.End_Time
end as 'End_Time',
m3.ts,
m3.USERID,
@lastUSER := m3.USERID
from (
select
m2.FIRSTNAME,
m2.EXTENSION,
m2.USERID,
m2.ts,
case
when @lastUSER <> m2.USERID
then '2010-01-01 00:00:00'
else @lastTS
end as 'Start_Time',
m2.ts as 'End_Time',
@lastUSER := m2.USERID,
@lastNAME := m2.FIRSTNAME,
@lastTS := m2.ts
from (
select
m1.EXTENSIONID,
m1.FIRSTNAME,
m1.EXTENSION,
m1.USERID,
convert_tz(m1.ts,'UTC','America/Denver') as ts
from
mxuser as m1
order by
USERID asc,
ts asc
) as m2,
(select @lastUSER := 0,
@lastNAME := '',
@lastTS := '0000-00-00 00:00:00') as SQLVars
order by
m2.USERID asc,
End_Time desc,
Start_Time desc
) as m3,
(select @lastUSER := 0) as SQLVars
order by
m3.USERID asc,
m3.End_Time desc,
m3.Start_Time desc
此查询的结果集,当从一开始就与我的示例一起使用时,会产生如下输出:
Name Extension USERID AGP_Start_Date AGP_End_Date
Johnny Gorman 51980 4389116109 2010-01-01 00:00:00 2019-07-15 03:00:24
James Sutherland 51980 4389116109 2019-07-15 03:00:24 2019-08-08 14:32:00
James Sutherland 51980 4389116109 2019-08-08 14:32:01 2019-08-13 23:59:59
Sara Sarason 51802 4399610820 2010-01-01 00:00:00 2019-08-13 23:59:59
一个很好的排序列表,加入起来很简单。对于共享相同 USERID 的人,有效日期和无效日期之间没有重叠:当我执行连接时,我确信我正在连接到唯一一个对计时行有效的用户行加入到。
只要我运行把它作为一个独立的查询,就是。
当我 运行 它在我的计时存储过程中时,它产生的结果如下:
Name Extension USERID AGP_Start_Date AGP_End_Date
Johnny Gorman 51980 4389116109 2016-01-01 00:00:00 2019-08-08 14:32:00
James Sutherland 51980 4389116109 2019-07-15 03:00:24 2019-08-08 14:32:00
James Sutherland 51980 4389116109 2019-08-08 14:32:01 2019-08-13 23:59:59
Sara Sarason 51802 4399610820 2010-01-01 00:00:00 2019-08-13 23:59:59
天哪,什么?现在,日期范围彼此重叠,当我将此 table 加入我的计时 table 时,它们会重复行。但奇怪的是它会相同错误的结果一致。
为什么会这样?这似乎与我用来从前一行中获取值以在当前行中进行计算的会话变量有关;就像他们计算不同步,或者行之间没有正确刷新一样。即使我终止会话并重新启动,也会发生同样的事情。
(在你问之前,不幸的是,没有 CTE 对我来说不是一个选择。:(
因此,答案是将用户日期范围查询包装在它自己的存储过程中,并在计时存储过程中调用它。它现在按预期工作。
我不知道为什么。
所以。奇怪的情况。我在与之交互的数据库中有一个用户 table。它看起来像这样:
EXTENSIONID USERID FIRSTNAME EXTENSION ts
448980 4389116109 Johnny Gorman 51980 2019-07-15 03:00:24
683597 4389116109 James Sutherland 51980 2019-08-08 14:32:00
683598 4399610820 Sara Sarason 51802 2019-08-12 15:38:21
683599 4389116109 James Sutherland 51980 2019-08-12 16:32:32
基本上,USERID 是我们员工计时 table 的外键,而且有问题的是,它 不是 对一个用户唯一的:如果我们不授予一个新用户一个新的 USERID 当我们为他们分配他们的 EXTENSION 时,他们将接管该 EXTENSION 的最后持有者的 USERID(正如你在上面看到的 Johnny Gorman 和 James Sutherland 所发生的那样)。
此外,正如您在 James Sutherland 身上看到的那样,一个特定的用户可以有多个具有相同 USERID 的行。 EXTENSIONID 是 table 的主键,它 是 唯一的,但它是另一组 table 的外键。
table 的时间戳字段最后有用。因此,换句话说,时间戳将小于或等于该时间戳的所有内容都属于该行,直到先前的时间戳。
换句话说,为了让我的用户 table 附加到我的计时数据,我过去必须根据时间戳执行相关子查询,如下所示:
select * from timekeeping_tables as tt
inner join USERS as u on tt.USERID = u.USERID
and u.ts = (select max(ts) from USERS where ts <= tt.ENDTIME and USERID = u.USERID)
除了速度之外,这在所有方面都工作得很好:对如此大的数据集进行相关子查询需要很长时间。因此,相反,我想出了一种方法来为 USERS table 中的每一行创建一个有效日期和无效日期列表,这样加入将是对 USERID 和 [ 之间的一个简单的相等匹配=48=] 子句在 Effective/Ineffective 日期上。它看起来像这样:
select
mx.FIRSTNAME as 'Name',
mx.EXTENSION as 'Extension',
mx.USERID,
min(mx.Start_Time) as 'AGP_Start_Date',
max(mx.End_Time) as 'AGP_End_Date'
from (
select
m3.FIRSTNAME,
m3.EXTENSION,
m3.Start_Time,
case
when @lastUSER <> m3.USERID
then subdate(adddate(curdate(),interval 1 day), interval 1 second)
else m3.End_Time
end as 'End_Time',
m3.ts,
m3.USERID,
@lastUSER := m3.USERID
from (
select
m2.FIRSTNAME,
m2.EXTENSION,
m2.USERID,
m2.ts,
case
when @lastUSER <> m2.USERID
then '2010-01-01 00:00:00'
else @lastTS
end as 'Start_Time',
m2.ts as 'End_Time',
@lastUSER := m2.USERID,
@lastNAME := m2.FIRSTNAME,
@lastTS := m2.ts
from (
select
m1.EXTENSIONID,
m1.FIRSTNAME,
m1.EXTENSION,
m1.USERID,
convert_tz(m1.ts,'UTC','America/Denver') as ts
from
mxuser as m1
order by
USERID asc,
ts asc
) as m2,
(select @lastUSER := 0,
@lastNAME := '',
@lastTS := '0000-00-00 00:00:00') as SQLVars
order by
m2.USERID asc,
End_Time desc,
Start_Time desc
) as m3,
(select @lastUSER := 0) as SQLVars
order by
m3.USERID asc,
m3.End_Time desc,
m3.Start_Time desc
此查询的结果集,当从一开始就与我的示例一起使用时,会产生如下输出:
Name Extension USERID AGP_Start_Date AGP_End_Date
Johnny Gorman 51980 4389116109 2010-01-01 00:00:00 2019-07-15 03:00:24
James Sutherland 51980 4389116109 2019-07-15 03:00:24 2019-08-08 14:32:00
James Sutherland 51980 4389116109 2019-08-08 14:32:01 2019-08-13 23:59:59
Sara Sarason 51802 4399610820 2010-01-01 00:00:00 2019-08-13 23:59:59
一个很好的排序列表,加入起来很简单。对于共享相同 USERID 的人,有效日期和无效日期之间没有重叠:当我执行连接时,我确信我正在连接到唯一一个对计时行有效的用户行加入到。
只要我运行把它作为一个独立的查询,就是。
当我 运行 它在我的计时存储过程中时,它产生的结果如下:
Name Extension USERID AGP_Start_Date AGP_End_Date
Johnny Gorman 51980 4389116109 2016-01-01 00:00:00 2019-08-08 14:32:00
James Sutherland 51980 4389116109 2019-07-15 03:00:24 2019-08-08 14:32:00
James Sutherland 51980 4389116109 2019-08-08 14:32:01 2019-08-13 23:59:59
Sara Sarason 51802 4399610820 2010-01-01 00:00:00 2019-08-13 23:59:59
天哪,什么?现在,日期范围彼此重叠,当我将此 table 加入我的计时 table 时,它们会重复行。但奇怪的是它会相同错误的结果一致。
为什么会这样?这似乎与我用来从前一行中获取值以在当前行中进行计算的会话变量有关;就像他们计算不同步,或者行之间没有正确刷新一样。即使我终止会话并重新启动,也会发生同样的事情。
(在你问之前,不幸的是,没有 CTE 对我来说不是一个选择。:(
因此,答案是将用户日期范围查询包装在它自己的存储过程中,并在计时存储过程中调用它。它现在按预期工作。
我不知道为什么。