Нормализация или сегментирование временных меток SQL стандартным способом в Oracle / H2

У меня есть таблица SQL foo в Oracle с отметкой времени bar. Я хочу обновить метки времени, чтобы они соответствовали максимальной метке времени в диапазоне 8–16 секунд. (Временные метки в любом случае приходят «группами»; они либо меньше 8 секунд, либо больше 16 секунд.) Да, и я провожу тесты с H2. Я пробовал это:

UPDATE foo update_foo SET bar =
  (SELECT MAX(bar) FROM foo
    WHERE bar > update_foo.bar - interval '8' second
        AND bar < update_foo.bar + interval '8' second)

H2 это не понравилось. Верен ли мой синтаксис для Oracle, если я хочу сделать это стандартным способом? Проблема в H2 или в моем синтаксисе? Или есть способ лучше?

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
0
147
2

Ответы 2

Это Н2. Ваш оператор соответствует Oracle 12c и тому времени, когда были введены временные метки (10g?).

Лучший способ зависит от H2, чего я не знаю.

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

Подход грубой силы, который должен быть довольно медленным, заключался бы в открытии курсора для

select key, max(bar) from foo group by key

и в цикле выберите строку и выполните следующее:

update foo set bar = max_fetched_bar where key = fetched_key

Ужасный. Совершенно ужасно. Но, возможно, обновление и выбор достаточно просты для анализа в H2.

Если H2 поддерживает выполнение анонимных блоков PL / SQL, тогда вы можете выполнить исходное обновление в блоке PL / SQL и, надеюсь, избежать H2.

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

Предполагая, что ваши данные:

create table foo (
  bar timestamp
);

insert into foo (bar) values ('2018-01-01 12:34:56');
insert into foo (bar) values ('2018-01-01 12:34:52');
insert into foo (bar) values ('2018-01-01 12:34:57');
insert into foo (bar) values ('2018-01-02 12:34:10');
insert into foo (bar) values ('2018-01-02 12:34:11');

Запрос:

update foo update_foo set bar =
  (select max(bar) from foo
    where bar > dateadd('second', -8, update_foo.bar)
        and bar < dateadd('second', 8, update_foo.bar)
);

Результат:

BAR                      
---------------------
2018-01-01 12:34:57.0    
2018-01-01 12:34:57.0    
2018-01-01 12:34:57.0    
2018-01-02 12:34:11.0    
2018-01-02 12:34:11.0    

Другие вопросы по теме