【问题标题】:complex sql query for finding the average working time of a person in office用于查找一个人在办公室的平均工作时间的复杂 sql 查询
【发布时间】:2012-02-17 02:46:27
【问题描述】:

我需要使用基于 oracle 的查询来检索员工的工作时间,即员工根据事务表中的事务进入和外出的时间。

事务表有一个可用于此目的的日期时间字段。

所涉及的步骤如下: 1)找到一个日期的第一笔交易和同一日期的最后一笔交易——这将是他在该日期的时间和超时 2) 计算总时间为每个日期所有时间的平均值,类似地做超时

事务表如下:transctn(transid, resourceid, event, currentdate)

第二个要求是找到每天执行的平均交易,这基本上是找到每天的transids计数,然后平均。

最终的答案应该是,当提供用户 ID 时,查询的返回结果是:

frequent working time(based on average): 9:43 am - 6:45 pm
average transactions performed/day = 43

如果 Transctn 是我的 Domain 类,我如何在 oracle SQL 中或更巧妙地使用 Hibernate 编写上述要求

我有这样的事情:

select 'frequent working time: '
    ||(select rtrim(to_char(min(currentdate),'hh:mi pm')) from transctn)
    ||' - '||(select rtrim(to_char(max(currentdate),'hh:mi pm')) from transctn)
    ||', average transactions performed/day = '
    ||(select rtrim(to_char(count(distinct transid)/
        count(distinct(to_char(currentdate,'rrmmdd')))) from transctn)
from dual

【问题讨论】:

  • 我有类似这样的 SELect '频繁工作时间:'||(select rtrim(to_char(min(currentdate),'hh:mi pm')) from transctn) ||' - '||(select rtrim(to_char(max(currentdate),'hh:mi pm')) from transctn) ||', 平均事务执行/天 = ' ||(select rtrim(to_char(count(distinct transid)) /count(distinct (to_char(currentdate,'rrmmdd')))) from transctn) from dual

标签: oracle hibernate


【解决方案1】:

首先,您的查询有很多来自同一个表的选择粘在一起,效率不高,并且比必要的更难阅读。 rtrim 没有做任何事情,因为您已经指定了格式。你所拥有的可以重写为:

select 'frequent working time: '|| to_char(min(currentdate),'hh:mi pm')
        ||' - '|| to_char(max(currentdate),'hh:mi pm'),
    'average transactions performed/day = '
        || to_char(count(distinct transid)
            /count(distinct to_char(currentdate,'rrmmdd')))
from transctn;

但这并没有正确平均,并且不适用于特定用户。我假设这是家庭作业,并且本着网站的一贯精神,尝试给你指点而不是完整的答案......

1) 查找日期的第一笔交易和最后一笔交易 同一日期 - 那将是他在该日期的时间和超时

您离这里不远,但您按日期分类。要获取每个用户每天的进出时间,您可以使用:

select resourceid, trunc(currentdate), min(currentdate), max(currentdate)
from transctn
group by resourceid, trunc(currentdate)
order by resourceid, trunc(currentdate);

2) 将总时间计算为每个时间所有时间的平均值 日期,超时也一样

您不能直接在 Oracle 中平均日期;你会得到ORA-00932: inconsistent datatypes: expected NUMBER got DATE。有多种方法可以达到效果,您只需要找出一种安全的方法来将日期 - 或者更具体地说是时间部分 - 视为数字。例如,您可以将时间部分视为实际时间与一天开始之间的差异,Oracle 将其返回为一个数字:

select avg(min(currentdate) - trunc(currentdate)),
    avg(max(currentdate) - trunc(currentdate))
from transctn
group by trunc(currentdate);

但是您不必将那个小数转换回可识别的东西。一种方法是将数字添加到任意固定日期,然后将时间部分提取为字符串,就像您已经在做的那样:

select to_char(date '2000-01-01' + avg(min(currentdate) - trunc(currentdate)),
        'HH:MI pm') as avg_time_in,
    to_char(date '2000-01-01' + avg(max(currentdate) - trunc(currentdate)),
        'HH:MI pm') as avg_time_out
from transctn
group by trunc(currentdate);

这看起来很乱,您可能会找到更好的方法。如果是家庭作业,那么我会假设你已经学会了做这类事情的方法,或者可以适应的东西。

这仍然适用于所有资源,因此您需要添加一个过滤器以限制一个用户 ID。希望这也能为您提供一些解决第二个要求的想法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-09
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多