сложный SQL-запрос для определения среднего рабочего времени человека в офисе - PullRequest
0 голосов
/ 17 февраля 2012

Мне нужно получить с помощью оракула запрос рабочего времени сотрудника, которое является временем прихода и ухода сотрудника на основе его транзакций в таблице транзакций.

Таблица транзакций имеет поле даты и времени, которое можно использовать для этой цели.

Шаги должны быть следующими: 1) найти первую транзакцию на дату и последнюю транзакцию на ту же дату - это будет его время и тайм-аут на эту дату 2) рассчитать общее время ожидания как среднее значение для всех дат на каждую дату, аналогично для времени ожидания

Таблица транзакций выглядит следующим образом: transctn(transid, resourceid, event, currentdate)

Второе требование - найти среднее количество транзакций, выполненных за день, то есть, в основном, найти количество транзакций за каждый день, а затем усреднить их.

Окончательный ответ должен быть, если при запросе идентификатора пользователя указан возвращаемый результат:

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

Как мне написать вышеупомянутое требование в Oracle SQL или более разумно, используя Hibernate, если Transctn является моим классом домена

У меня есть что-то вроде этого:

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

1 Ответ

1 голос
/ 18 февраля 2012

Во-первых, ваш запрос содержит множество вариантов выбора из одной и той же таблицы, которые объединены, что неэффективно и затрудняет чтение по сравнению с необходимостью. И 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);

Это выглядит грязно, и вы можете найти лучший способ сделать это. Если это домашнее задание, то я бы предположил, что вас научили методам такого рода вещей или тому, что можно приспособить для применения.

Это все еще для всех ресурсов, поэтому вам нужно добавить фильтр, ограничивающий один идентификатор пользователя. Надеюсь, это даст вам некоторые идеи для решения второго требования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...