mysql - 存储过程中的临时表返回的值与常规查询中的值不同

标签 mysql sql stored-procedures database-administration

所以。奇怪的情况。我在与之交互的数据库中有一个用户表。它看起来像这样:

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 是我们的员工考勤表的外键,但有问题的是,它对于一个用户来说不是唯一的:如果我们在分配新用户时没有向新用户授予新的 USERID他们的扩展,他们只会接管该扩展的最后持有者的 USERID(正如您在上面的 Johnny Gorman 和 James Sutherland 中看到的那样)。

此外,正如您在 James Sutherland 中看到的那样,特定用户可以拥有具有相同 USERID 的多行。 EXTENSIONID 是表的主键,并且它是唯一的,但它是另一组表的外键。

表的时间戳字段是最后有用的。因此,换句话说,时间戳表明所有小于或等于该时间戳的内容都属于该行,直到前一个时间戳为止。

换句话说,为了将我的用户表附加到我的计时数据,我过去必须根据时间戳执行相关子查询,如下所示:

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 表中的每一行创建有效日期和无效日期的列表,以便连接将是 USERID 上的简单相等匹配和 USERID 上的 Between 子句有效/无效日期。它看起来像这样:

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

天哪,什么?现在,日期范围相互重叠,当我将此表连接到计时表时,这会重复行。但奇怪的是,它会始终产生相同的错误结果。

为什么会发生这种情况?这似乎与我用来从前一行获取值以在当前行中进行计算的 session 变量有关;就像它们计算不同步,或者行之间没有正确刷新一样。即使我终止 session 并重新启动,也会发生同样的事情。

(在你问之前,不幸的是,没有 CTE 对我来说不是一个选择。:(

最佳答案

因此,答案是将用户日期范围查询包装在其自己的存储过程中,并在计时存储过程中调用它。现在它按预期工作了。

我不知道为什么。

关于mysql - 存储过程中的临时表返回的值与常规查询中的值不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57484826/

相关文章:

mysql - 如何通过 ip 地址查询加快国家检测?

sql - 是否可以在 unnest 中使用 array_agg 结果? |数据库

SQL Server : stored procedure IFNULL check

stored-procedures - 流利的NHibernate无需hbm.xml映射即可查询存储过程

php - 在 LOAD DATA LOCAL INFILE 中收到错误消息

php - SQLSTATE[HY093] : Invalid parameter number: parameter was not defined

php - LAMP/Laravel - 报告生成最大化单个 CPU

mysql - SQL查询中的Excel日期参数

sql查询从重复项中查找缺失值

java - 从 Java 执行存储过程,而不是使用 JDBC CallableStatement