Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Интервалы времени между записями по одному полю

Есть таблица с двумя столбцами: Код, Дата. Как посчитать интервалы времени между записями. Нужно в записи на 07:00:00 видеть разницу между 7:10:10 и 07:00:00 = 00:10:10 и так далее. т.е в третьем столбце нужно видеть временной интервал между текущей записью и следующей. Как это реализовать, подскажите!? Помогите пожалуйста!
Ответ:
Сообщение от Виктор Михалыч
когда запрос на все записи, а их более 67 000 Access зависает.
Запросы такого типа всегда медленные, также как например запросы нарастающим итогом. На больших объемах нужна временная таблица.
Сделайте таблицу со счетчиком id и полями Код, Дата. Назовем таблицу Temp. Инсертом вставьте туда Код и Дата. Тогда простой и быстрый запрос к Temp даст нужное
SQL
1
2
SELECT Temp.Код, Temp.Дата, t1.Дата-Temp.Дата AS Период
FROM Temp INNER JOIN Temp AS t1 ON Temp.id=t1.id-1
На таблице со 100 тысячами записей такой запрос работал секунду. Еще 3-4 секунды понадобилось на вставку данных в Temp

Добавлено через 6 минут
Да еще. При вставке надо отсортировать таблицу по дате.
SQL
1
2
INSERT INTO Temp (Код, Дата)
SELECT Код, Дата FROM Таблица1 ORDER BY Дата
Вопрос: Подсчёт часов между датами

Добрый день!
Прошу помочь решить задачу с подсчётом количества часов между двумя датами в формате времени __:__ . В таблице есть начальная дата D1, начальное время T1, конечная дата D2, конечное время T2.
По сути должно быть так: (D2-D1)*24+(T2-T1). Затык в том, что после подсчёта количества часов между D2 и D1 итог выводится в основном формате поля. Как этот итог преобразовать в формат времени __:__?
К примеру:
D1 - 01.08.16
D2 - 03.08.16
(D2-D1)*24 = 48
Как эти 48 превратить в 48:00? Чего то всю голову сломал.
Ответ:
Сообщение от PuhKMV
Тоже немного не въехал, но Кажись если в свободном поле запроса в режиме конструктора вставить сие творение и вместо знака вопроса написать что то любое слово, типа - часов всего и двоеточие потом выражение с истинными именами полей, то Кажись все на вскидку должно рассчитаться правильно.
Разве что для синтаксиса запроса в режиме конструктора вместо просто запятой нужно точку с запятой везде проставить.
Но как уже кажется упоминал, это на вскидку.
Да, действительно. Получилось сделать это через запрос. Благодарю за подсказку!
Вопрос: Выборка отрезков времени между сеансами посещения

Всем привет! Дело такое: допустим есть таблица посещений клиента Users с полями Fam, Im, Otch, DatePos в таком виде:
Иванов Иван Иванович 2016-02-01
Иванов Иван Иванович 2016-02-02
Иванов Иван Иванович 2016-02-05
Иванов Иван Иванович 2016-02-08

Мне требуется сделать такую выборку, что бы выдались строки с последовательными промежутками между посещениями пользователя такого вида:
Иванов Иван Иванович 2016-02-01 2016-02-02
Иванов Иван Иванович 2016-02-02 2016-02-05
Иванов Иван Иванович 2016-02-05 2016-02-08

Я написал такой запрос:
SELECT
    u.FAM,
    u.IM,
    u.OTCH,
    u.DatePos,
    t.DatePos
FROM Users u
JOIN    (
            SELECT
            u1.FAM,
            u1.IM,
            u1.OTCH,
            u1.DatePos
        FROM Users u1
    )
     t ON t.FAM = u.FAM AND t.DatePos > u.DatePos
ORDER BY u.DatePos


Получается такая картина:
Иванов Иван Иванович 2016-02-01 2016-02-02
Иванов Иван Иванович 2016-02-01 2016-02-05
Иванов Иван Иванович 2016-02-01 2016-02-08
Иванов Иван Иванович 2016-02-02 2016-02-05
Иванов Иван Иванович 2016-02-02 2016-02-08
Иванов Иван Иванович 2016-02-05 2016-02-08

То есть присутствуют лишние строки:
Иванов Иван Иванович 2016-02-01 2016-02-05
Иванов Иван Иванович 2016-02-01 2016-02-08
Иванов Иван Иванович 2016-02-02 2016-02-08

Чувствую, что где-то прям чуть-чуть не догоняю.. То ли понедельник, то ли вечер, то ли всё вместе ))) Может завтра сутра озарит мою голову решение, но пока туплю...
Кому не сложно - помогите дельным советом )))
Ответ: iljy, ну я руководствовался вот этим кодом:
WITH balance_details
AS
(
SELECT * FROM (
VALUES
('Tom','20140101',100),
('Tom','20140102',120),
('Tom','20140103',150),
('Tom','20140104',140),
('Tom','20140105',160),
('Tom','20140106',180),
('Jerry','20140101',210),
('Jerry','20140102',240),
('Jerry','20140103',230),
('Jerry','20140104',270),
('Jerry','20140105',190),
('Jerry','20140106',200),
('David','20140101',170),
('David','20140102',230),
('David','20140103',240),
('David','20140104',210),
('David','20140105',160),
('David','20140106',200)
) AS t (customer, balancedate,balance)
),
balance_cte AS
(
SELECT
ROW_NUMBER() OVER (PARTITION BY customer ORDER BY balancedate) rn
,(ROW_NUMBER() OVER (PARTITION BY customer ORDER BY balancedate))/2 rndiv2
,(ROW_NUMBER() OVER (PARTITION BY customer ORDER BY balancedate) + 1)/2 rnplus1div2
/*
,COUNT(*) OVER (PARTITION BY customer) partitioncount
*/
,customer
,balancedate
,balance
FROM balance_details
)
SELECT
rn
,rndiv2
,rnplus1div2
,customer,balancedate,balance
,CASE WHEN rn%2=1 THEN MAX(CASE WHEN rn%2=0 THEN balance END) OVER (PARTITION BY customer,rndiv2) ELSE MAX(CASE WHEN rn%2=1 THEN balance END) OVER (PARTITION BY customer,rnplus1div2)
END AS balance_lag
,CASE WHEN rn%2=1 THEN MAX(CASE WHEN rn%2=0 THEN balance END) OVER (PARTITION BY customer,rnplus1div2) ELSE MAX(CASE WHEN rn%2=1 THEN balance END) OVER (PARTITION BY customer,rndiv2)
END AS balance_lead
/*
,MAX(CASE WHEN rn=1 THEN balance END) OVER (PARTITION BY customer) AS first_value
,MAX(CASE WHEN rn=partitioncount THEN balance END) OVER (PARTITION BY customer) AS last_value
,MAX(CASE WHEN rn=4 THEN balance END) OVER (PARTITION BY customer) AS fourth_value
*/
FROM balance_cte
ORDER BY customer,balancedate



И как-то мне тяжелее далось понимание этих операций.
Вопрос: Триггер для вычисления затраченного времени (разницы между датой/временем в двух полях)

Добрый день всем.
Не имею опыта и знаний для создания триггеров, поэтому прошу помощи.
На SQL Server есть таблица 'SAMO_HandlingList'. Помимо прочих полей, в ней есть поля 'conclusion_sent_time' и 'conclusion_executed_time' с типом данных datetime (хранится в формате 2017-02-09 17:03:22.000).
Изначально запись в таблицу вносится с заполненным значением поля 'conclusion_sent_time' (дата/время отправки заключения), а поле 'conclusion_executed_time' имеет значение NULL. Позже пользователь вносит дату/время выполнения заключения ('conclusion_executed_time').
Задача - вычислить затраченное время между датой/временем отправки заключения и датой/временем его исполнения и записать это значение в поле 'execution_sentence'.

Есть желание реализовать это триггером, который вычислял бы это значение при каждом изменении записи (внесением и/или времени исполнения.
Но ввиду отсутствия знаний и опыта пока ничего не получилось.
Вот что смог создать:

SQL
1
2
3
4
5
6
7
8
9
10
11
12
CREATE TRIGGER [dbo].[tgrHandlingListUpdate]
   ON [dbo].[SAMO_HandlingList]
   AFTER UPDATE
AS
DECLARE @DateTime_old datetime, @DateTime_new datetime, @execution TIME, @id INT
BEGIN
      SELECT @DateTime_new = conclusion_executed_time, @id = id FROM inserted
      SELECT @DateTime_old = conclusion_sent_time FROM SAMO_HandlingList
      IF (@DateTime_new > @DateTime_old)
      UPDATE SAMO_HandlingList SET execution_sentence = (@DateTime_new - @DateTime_old)
      WHERE id = @id
END
Но он не работает.

Прошу помочь с кодом, как создать такой триггер?
Заранее спасибо!
Ответ:
Сообщение от nikan131
чтоб разница записывалась более читабельно для пользователя
"Читабельность" определяется отображением в SELECT, а не форматом хранения.
Вопрос: Посчитать время

доброго времени суток. есть тест. пользователь отвечает на вопросы и при каждом ответе в бд заносится время. есть нужда в том, чтобы посчитать время за которое пользователь прошел тест. конечно, можно взять время старта и время окончания, сделать соответствующие вычисления и получить время. однако, пользователь может начать тест, прервать его в любой момент и продолжить хоть через год. соответственно, если он так и сделает, то при таких вычислениях время прохождения теста будет больше года, хотя по факту заняло, например, минут 20. то есть нужно посчитать время между каждым ответом. а вот как это сделать - не могу уразуметь. хотел бы прочесть идеи реализации сей проблемы. спасибо всем заранее
Ответ: пардон! синтаксис неправильно написал, сам только начал изучать =)
а, вот так если попробовать:
PHP
1
2
3
4
$f = $x+1;
$name1 = 'date'.$f;
$name2 = 'date'.$x;
$tq = $row[$name1] - $row[$name2];
Вопрос: формирование построчно интервалов времени

Добрый день!

Есть такая задача.

Имеем выгрузку данных по талонам электронной очереди в виде таблицы tickets

report_date (отчетная дата), event_time (время отрыва талона), ticket_id (id_талона)

report_date event_time ticket_id
20.01.2018 09:30:31 И001
20.01.2018 09:30:38 И002
20.01.2018 09:31:01 И003
20.01.2018 09:32:01 И004


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

report_date previous next
20.01.2018 09:30:31 09:30:38
20.01.2018 09:30:38 09:31:01
20.01.2018 09:31:01 09:32:01



Корректно ли использовать запрос в таком виде или можно как-то решить через оконные функции?

/****** Скрипт для команды SelectTopNRows из среды SSMS  ******/

Select t.report_date,t.event_time,t1.event_time

from

(
  SELECT
	[report_date]
      ,	[event_time]

  FROM tickets

) t
  cross apply

  (
	  select top 1 event_time 
	  FROM tickets
	  Where t.report_date = report_date
	  and event_time > t.event_time
  )

  t1

  order by t.report_date, t.event_time
Ответ: Michail A.,

Что то вроде
lead(event_time) over (order by event_time)

Конечно же вам надо удостовериться, что event_time будет у вас сортироваться так как вам нужно. Если у вас event_time не в правильном формате, то сортировка будет неправильной.
Вопрос: Подсчет отрезков времени внутри заданного интервала

Добрый день, очень нужна помощь, я новичок в SQL и не могу составить корректный запрос
есть таблица

id type start stop
1 avaliable 18-01-17 10:05:00 18-01-17 10:25:00
2 pause 18-01-17 10:30:00 18-01-17 10:10:45
3 avaliable 18-01-17 10:45:00 18-01-17 16:25:00
4 pause 18-01-17 16:25:00 18-01-17 16:50:00
5 avaliable 18-01-17 16:50:00 18-01-17 18:40:00
6 pause 18-01-17 18:40:00 18-01-17 19:10:00


т.е. человек включил систему, потом в течении дня становился на паузу, рабочий день с 10:20 до 19:00 включить/выключить систему или встать/выйти с паузы можно за этим интервалом, как составить запрос, чтобы посчитать время работы (или паузы именно в промежутке между 10:20 и 19:00?
Ответ: у оператора там куча состояний, звонит или не звонит, доступен или в паузе, мне нужно вычесть суммарное время одного состояния и вычесть его из продолжительности рабочего дня

Добавлено через 1 минуту
и это конкретное состояние мне нужно учитывать только в рамках рабочего дня, а не каждый раз, когда ему вздумалось чего-то поделать
Вопрос: Group BY, ограничение вывода LIMIT и подсчёт результатов

Всем привет, столкнулся со следующей проблемой. Имеется таблица visits (фиксирует посещения пользователей).

Задача: выводить посещаемость по дням с возможностью постраничного вывода.

В отличии от простых запросов (без GROUP BY) подобных проблем нет. Но тут считать общее кол-во результатов (без LIMIT) mysql отказывается.

На данный момент такой вывод реализован через аж целых 3 запроса:
SELECT date, COUNT(*) as count FROM visits WHERE .... GROUP BY date ORDER BY date DESC LIMIT 0, 30 - это основной
SELECT date, COUNT(*) as count FROM visits WHERE .... GROUP BY date - это для подсчёта
SELECT FOUND_ROWS() as cnt - это сам подсчёт

Скорее всего со временем - это дело начнет жутко тормозить при больших объёмах данных, хотелось бы посоветоваться, как сделать лучше и правильней. Заранее благодарю за ответы.
Ответ: SELECT count(distinct `date`) FROM visits WHERE ...; - для подсчета.

Один запрос далеко не всегда быстрее двух. И как раз использовать SQL_CALC_FOUND_ROWS не стоит. См .
Вопрос: Работа с текущим временем

Здравствуйте.
Подскажите пожалуйста ,как можно реализовать операцию с проведением подсчёта показаний приборов учета(два раза в сутки утро и вечер) согласно текущему времени Now()?
Более понятно.
Пример:
При снятии замера оператор профукал время и записал показания в 10:10(обычно заносится в 9:00"+-" 5 минут) к примеру 23.03.2016г.
Предыдущий замер был на 9:05 "22.03.2016". С подсчётом и разработкой БД для замеров очень помогла Техник-Сан. Как пересчитать получившийся значение за 25:35мин на 24 часа(суточный приведённый). На калькуляторе без проблем(делим и умножаем в минутах или в часах в числовом формате), в БД тоже наверное требуется форматировать разницу в числовое значение. Как?

Добавлено через 20 минут
Косяк: за 25:05 мин в 24:00. Простите
Ответ:
Сообщение от mobile
Да, не будет. В запросе нет ни текущей даты Date(), ни текущего времени Time() или Now(). Из текста запроса неочевидно как туда вставить текущие дату/время
Придётся мудрить с самой структурой БД (учёт замера с привязкой к текущему времени). Ладно на работе попробую как-нибудь разобраться. Книг надо только побольше скачать.
Вопрос: Подсчет текущего остатка триггером

Написал триггер для подсчета текущего остатка по счету, он не всегда срабатывает. Т.е. иногда появляется неверная сумма в поле acc.current_rest. Не могу понять что я сделал неверно.
DDL (не абсолютно точный но в сути полностью повторяющий боевой код) под спойлером.

+
-- счета клиентов
create table acc(id integer not null primary key, client integer not null, account_type integer not null, current_rest number default 0 not null);

-- движение по счетам клиентов
create table acc_move(id integer not null primary key, acc integer not null references acc(id), dt date not null, value number not null);

-- тип для хранения одного движения
create type t_acc_move as object(acc integer, value number);
/

-- коллекция для накопления изменений
create type tt_acc_move as table of t_acc_move;
/

-- триггер для подсчета остатка
CREATE OR REPLACE TRIGGER trg$acc_move_rest
  for insert or update or delete on acc_move
  compound trigger

  l_moves tt_acc_move;

  before statement is
  begin
    l_moves := tt_acc_move();
  end before statement;

  before each row is
    l_idx    number := l_moves.count + 1;
    l_values t_acc_move := t_acc_move(0, 0);
  begin
    l_moves.extend(1);
    if inserting
    then
      l_values.acc := :new.acc;
      l_values.value := :new.value;
    elsif updating
    then
      if :new.acc = :old.acc
      then
        l_values.acc := :new.acc;
        l_values.value := :new.value - :old.value;
      else
        l_moves.extend(1);

        l_values.acc := :old.acc;
        l_values.value := - :old.value;
        l_moves(l_idx + 1) := l_values;

        l_values.acc := :new.acc;
        l_values.value := :new.value;
      end if;
    elsif deleting
    then
      l_values.acc  := :old.acc;
      l_values.value := - :old.value;
    end if;
    l_moves(l_idx) := l_values;
  end before each row;

  after statement is
  begin
    merge into acc a
    using (select acc,
                  sum(value) value
             from table(l_moves)
            group by acc) t
    on (t.acc = a.id)
    when matched then
      update
         set a.current_rest = a.current_rest + t.value;
  end after statement;

end;
/
Ответ: Проверил. Когда row level триггер во время merge натыкается на неинициализированную коллекцию то выдает ошибку при попытке её расширить. Т.е. неверных значений это породить не может. И значит ошибка где-то в другом месте.