Вычислите рабочее время между 2 датами в PostgreSQL

Используйте прерывание!

tempfiles=( )
cleanup() {
  rm -f "${tempfiles[@]}"
}
trap cleanup 0

error() {
  local parent_lineno="$1"
  local message="$2"
  local code="${3:-1}"
  if [[ -n "$message" ]] ; then
    echo "Error on or near line ${parent_lineno}: ${message}; exiting with status ${code}"
  else
    echo "Error on or near line ${parent_lineno}; exiting with status ${code}"
  fi
  exit "${code}"
}
trap 'error ${LINENO}' ERR

... тогда, каждый раз, когда Вы создаете временный файл:

temp_foo="$(mktemp -t foobar.XXXXXX)"
tempfiles+=( "$temp_foo" )

и $temp_foo будет удален на выходе, и текущий номер строки будет распечатан. (set -e аналогично даст Вам поведение выхода на ошибке, , хотя оно идет с серьезными протестами и ослабляет предсказуемость и мобильность кода).

можно или позволить вызову прерывания error для Вас (в этом случае, он использует код выхода по умолчанию 1 и никакое сообщение), или назовите его сами и обеспечьте явные значения; например:

error ${LINENO} "the foobar failed" 2

выйдет с состоянием 2 и даст явное сообщение.

16
задан Erwin Brandstetter 9 February 2016 в 01:55
поделиться

1 ответ

Как насчет этого: создайте небольшую таблицу с 24 * 7 строками, по одной строке на каждый час в неделю.

CREATE TABLE hours (
  hour timestamp not null,
  is_working boolean not null
);

INSERT INTO hours (hour, is_working) VALUES
 ('2009-11-2 00:00:00', false),
 ('2009-11-2 01:00:00', false),
 . . .
 ('2009-11-2 08:00:00', true),
 . . .
 ('2009-11-2 15:00:00', true),
 ('2009-11-2 16:00:00', false),
 . . .
 ('2009-11-2 23:00:00', false);

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

SELECT t.id, t.start, t.end, SUM(CASE WHEN h.is_working THEN 1 ELSE 0 END) AS hours_worked
FROM mytable t JOIN hours h 
ON (EXTRACT(DOW FROM TIMESTAMP h.hour) BETWEEN EXTRACT(DOW FROM TIMESTAMP t.start) 
      AND EXTRACT(DOW FROM TIMESTAMP t.end))
  AND (EXTRACT(DOW FROM TIMESTAMP h.hour) > EXTRACT(DOW FROM TIMESTAMP t.start)
      OR EXTRACT(HOUR FROM TIMESTAMP h.hour) >= EXTRACT(HOUR FROM TIMESTAMP t.start))
  AND (EXTRACT(DOW FROM TIMESTAMP h.hour) < EXTRACT(DOW FROM TIMESTAMP t.end)
      OR EXTRACT(HOUR FROM TIMESTAMP h.hour) <= EXTRACT(HOUR FROM TIMESTAMP t.end))
GROUP BY t.id, t.start, t.end;
6
ответ дан 30 November 2019 в 16:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: