Реклама
Комментарии 52

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

>таймстамп
Уточните задачу, какой из них? Обычный timestamp, timestamp with timezone, или timestamp with local timezone?
с темпоральными данными работал мало, и к финансовой сфере его лучше не подпускать.
Не имею понятия, как оно там в финансовой сфере. Что, реально, упор на работу со временем, а не тупо подряд со всем и какими-то очередями?
Что хотел сделать автор кода?
Почему это может работать не так, как хотелось?
Как это исправить?

Очевидно плохо в этом только одно — задающий вопрос.
Любая задача имеет область определения: нельзя решить бином на множестве действительных чисел при отрицательном дискриминанте, нельзя сокращать на ноль и т.д. Постановщик задачи предложил рассмотреть все варианты, кроме правильного: автор кода точно знает, что хранится в таблице и что нужно получить в результате запроса. Снафу ожидаемо слился.
Если вы делаете реваерс инженинринг кода, написанного в стране, где все программисты танцуют и поют, то предложение, что «автор кода точно знает» — это самое последнее, что можно допускать
для дат использую форматы ODBC, всегда получаю одинаковый формат дат, не зависящий от региональных настроек
where DT >= {d'2020-03-02'} and DT < {d'2020-03-03'}

.
правда, наступаю на грабли №3, но никто не замечает
Довольно давно использую формат yyyy-MM-dd [HH:mm:ss] в работе.
Для отчетов на бек энде всегда использую их, и еще небыло ни одного клиента, которого это не устроило. Даже есть пример, когда отображение в UTC сняло напряженность между регионами
Еще в далеком 96-м впервые наткнулся на то, что с датой типа 13/06/96 проблем нет. А вот с 10/06/96 — «температура за бортом» зависит от локали. До этого кроме моего компа и компа отца (настроенных абсолютно одинаково) — других не «щупал».
sshikov, я работаю с MSSQL, и в нем таймстемп содержит дату, время и таймзону. Если нужно отображать время в определенной зоне, либо откорректировать зону без изменения времени, то для этого есть соответствующие функции.

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

Для большой интернациональной команды не подходите)))
Ну тогда вот вам еще: Events — это системное представление, в котором нет поля DT… Неплохо было бы уточнить, например: FROM [dbo].[Events]
WHERE как бы намекаэ что там как минимум дата. Причем не в системном формате
Совершенно нет. Там может быть строка. Знак «больше» или «меньше» — возможно с чуть большей вероятностью намекал бы на дату, но совершенно не факт.
Так что все построения стоит сломать и построить заново, если DT — это строка в которой хранится строковое представление даты [а рядом к примеру TM в виде строкового представления времени или для забубенистости — int или даже три int ]

если DT — это строка в которой хранится строковое представление

— а разве за такое не расстреливают?
Ну если не стреляют за собеседовательные вопросы, как в статье — то по-аналогии — нет.
Не чаще чем за неявные преобразования строк в даты без региональных настроек.
Events — это системное представление, в котором нет поля DT

прекрасный ответ!
Для начала бы неплохо указать про грабли в написании даты.
Даже если в поле хранится DATE и запрос вроде бы корректный, достаточно сделать
SET DATEFORMAT YDM

и запрос превращается в тыкву.
А всего лишь надо было написать в универсальном формате, или явно его указав при конвертации из строки
SELECT * FROM Events where DT='20200203'
SELECT * FROM Events where DT= Convert(date, '2020/02/03', 111)

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

Вот и в этой статье мы видим типичную ситуацию с «Токсичным собеседованием», где главная цель задающего вопросы — надуться от собственной важности и расчесать своё и без того громадное ЧСВ.

Видимо это какая-то специфика банковской сферы. И то сказать, в Россиюшке-то банки и тюрьма рука об руку ходят, а там уж недалеко до вопросов о двух стульях. Которые, как известно, и нужны для того, чтобы новичка «опустить».

На практике, конечно, это работает не так. И даже сам автор, решая подобные задачи на практике, действовал бы не так — потому что ему нужно было бы не наполнить соискателя чувством вины, чтобы снизить ожидаемую зарплату, а решить бизнес-задачу.

Итак, задача:

>Что хотел сделать автор кода?
>Как это исправить?
>Почему это может работать не так, как хотелось?

Итак, ответ:

Гаданиями занимаются дальше по улице в палатке гадалки и чудотворицы Мадам Эвелины, Потомственной Ясновидящей. Если вы пришли ко мне с куском кода, с вопросами — наверное вы УЖЕ ЗНАЕТЕ, что работает не так, и столкнулись с какой-то ошибкой? Назовите её, мы поищем источник и будем думать, как поправить. Это в том случае, если у нас нет ни автора кода (который возможно ещё работает у нас), ни технического задания (в котором, возможно, написано, что нужно было сделать), ни представителей заказчика/бизнеса (которые, возможно, способны прямо сказать, что именно они хотят).

В копилку забавных фактов — если поставить человеку задачу в правильном виде, то есть «выбрать данные за день, если поле даты такого-то формата» — большинство людей, которые «тупят» в ответ на идиотские вопросы, напишут правильный код. Просто потому что их мозг будет занят решением конкретной и полезной задачи, а не поиском ответов на идиотские вопросы про круглые люки и способы выбраться из блендера.

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

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

В реальном мире как минимум существует проблема, а не «ну-ка догадайся, чего я от тебя сейчас тут хочу».
Программисты нужны для написания нормального кода, в котором не будет таких проблем. А тех кто вынужден искать баги статическим анализом в «индукоде» — предлагаю выделить в отдельную категорию.
А мне нравится задачка, возьму на заметку. Только в формате «какие проблемы/сайд-эффекты могут возникнуть, при использовании такого запроса»

С деньгами в разных валютах все в сотни раз интереснее :)

Ну нельзя же так отсылку на полпути терять, персонажа-то так не в честь фазы луны назвали, а в честь хрестоматийного Situation Normal: All Fucked Up.


Ну и это, я вот вообще ни разу не специалист по DB, но я бы:


  • спросил интервьюера, с какого перепугу у нас нет триггера на insert и автозаполняемого поля utc_date, которое сохранит кучу нервов, если ивенты приходят в локальных таймзонах, или с задержками
  • спросил интервьюера, что за RDBMS, потому что $1 + integer '2' в постгресе, например, наверняка отработает быстрее (незначительно, но тем не менее)
  • спросил интервьюера, здоров ли он вообще, если думает, что «DT станет smalldatetime или datetime2» — это изменение, которое поломает вот только этот мой избранный простенький SELECT.

Но это я, я в базах ничего не понимаю, кроме того, что они данные как-то там хранят.

  1. Триггеры — это зло (по производительности). Не скажу за MS SQL, но в Oracle это так (ну и с какого перепуга там должны быть триггеры, когда можно обойтись дефолтными значениями?)
  2. Вопросы там задаёт интервьюер (но так то вообще речь не о том как быстро работает арифметика дат, а о том что она убивает использование индекса по полю (если не предпринимать дополнительных действий))
  3. Интервьюер возможно и не здоров (судя по тому как он строит беседу), но сей чудный запрос может убить (или сделать до ужаса непредсказуемым) простая смена региональных настроек (что легко может случиться, ага, даже на продакте) — это в отрыве от того, что он вообще, похоже, делает не то что задумывал разработчик (но так-то да, телепаты работают в соседнем отделе)
Триггеры — это зло (по производительности).

На INSERT? Производительно чего там просядет, а?


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

Нельзя, я даже написал, почему.


Вопросы там задаёт интервьюер [...]

Просто потому, что интервьюер — баран, и не умеет вести собеседования? Интервью — это не покупка билета в рабство, право задавать вопросы есть, очевидно, у всех.


простая смена региональных настроек (что легко может случиться, ага, даже на продакте)

Ой, все. Как вам там, в 1995 году-то живется? К проду доступа уже лет десять нигде прямого нет, и такие настройки не то, что сами поменяться не могут, их никто поменять не может, иначе девопсов надо гнать к чертям.

На INSERT? Производительно чего там просядет, а?

Переключения контекстов SQL/PL SQL (если мы продолжаем говорить за Oracle)
Нельзя, я даже написал, почему.

поясните? почему это нельзя default sysdate? (ну и чтобы дважды не вставать, как это связано с таймзонами?)
интервьюер — баран

пропущу (выход за спиной, если что)
К проду доступа уже лет десять нигде прямого нет

Блин, надо мужикам рассказать, а то они на своей техподдержке то и не знають.
Переключения контекстов SQL/PL SQL

Очень умные слова, наверное, на собеседованиях хорошо заходят. Oracle не станет медленнее отдавать все остальное, если в отдельной таблице есть триггер на INSERT.


почему это нельзя default sysdate?

Потому что обычно люди хотят знать, когда событие произошло, а не когда оно добралось до хранилища. Offline клиент в Сингапуре может выйти в сеть для синхронизации с вашим Ораклом спустя три часа после события. Так понятно?


они на своей техподдержке то и не знають

Я же говорю, привет девяностые.

Oracle не станет медленнее отдавать все остальное

Станет. Незначительно, но станет. Ну а вставка просядет так, что и к гадалке не ходи.
когда событие произошло, а не когда оно добралось до хранилища

Бинго! И как тут помогут триггеры?
Я же говорю, привет девяностые.

Здорово, здорово. Ещё не у всех базы в Docker-е лежат. Доступ к продуктовым БД ограничен и жестко залогирован, но он есть (у нас во всяком случае)
Станет. Незначительно, но станет.

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


Бинго! И как тут помогут триггеры?

Взять timestamp из того, что записал клиент (в свое время, в своей таймзоне, очевидно), и сделать из него нормальный utc_date. Вы хотите, чтобы я код написал, или что?

Не станет, если правильно настроить приоритеты

Глупости пишете, от просадки производительности инстанса никакие приоритеты не помогут. Впрочем, поучите меня настраивать Oracle (может что новое узнаю)
Вы хотите, чтобы я код написал, или что

Спасибо. Говнокода нам в собственном проде хватает.
Говнокода нам в собственном проде хватает.

Неудивительно, если вы только с пятого раза понимаете, чем статичное дефолтное значение отличается от триггера.

Вы же понимаете, что не правы? Что в самом начале сморозили несколько глупостей (это со всеми бывает)? Но продолжаете педалить тему с триггерами. Триггеры не нужны для вставки дат с таймзонами клиента. Есть куча менее кровавых решений. Хоть та же арифметика дат на клиенте.
Не станет, если правильно настроить приоритеты вставки для этой таблицы

Что такое «приоритет вставки»? Приведите пример. В гугл не посылать. Можете сослаться на документацию, например.
Вы хотите, чтобы я код написал, или что?

Да, приведите пример. Иначе создается впечатление, что вы, не зная ничего о бд (чуть выше вы сами об этом сказали), придумываете, как оно работает.

Далее. Писать комментарии часто хабр не дает, так что:
1. Триггер на инсерт отлично так просаживает вставку. По-моему, это очевидно. Но если кому-то нет, то причина: выполнение доп.действий при каждой вставке вставке помимо действий по самой вставке
2. Триггер (любой) не даст использовать параллельный DML (update /*+ pallallel */).
3. Валидация значений на вставку должна производиться в коде приложения/ХП либо значениями по умолчанию. А иначе
Кстати (чуть не забыл). Региональные настройки могут поменяться и на уровне сессии.

Автор статьи, зачем вы мучаете людей на интервью? Попробуйте сами решить задание, сформулированное схожим с вашим форматом: есть код


UPDATE table_name SET datetime2 = SYSDATETIME()
WHERE datetime2 IS NULL;
GO

Задача: Возвращать значение обновлённого времени. Ваше решение?

Зачем вы упрощаете автору задачу? Он должен сам догадаться что надо делать.

Либо использую OUTPUT, либо нестандартный синтаксис update set var=col=value

И если одним запросом обновиться 1000000 строк, то вы через OUTPUT вернёте такое же количество одинаковых сообщений? (одно и то же значение времени) Напишите, пожалуйста, более подробно про нестандартный синтаксис (или мне в личку))

Если не нагуглите то напишу после 8го, сейчас путешествую, на телефоне сиквеля нет

Изза турбулентности в экономике только сейчас обрался
Вот пример нестандартного синтаксиса:

create table T (n int)
GO
insert into T select 1
GO
declare @v int
update T set @v=n=n+1
select @v

Из-за @v=n добавляется Compute Scalar в план выполнения (примерно 1% от всей стоимости плана, но на 100000 строк вместо 46 ms выдаёт 156 ms)


DECLARE @v DATETIME2 = SYSDATETIME()
UPDATE table_name
SET n = @v
WHERE n IS NULL;
SELECT @v
GO

Конечно есть вероятность, что после DECLARE будет попадание в следующий такт CPU (поэтому; и конечно GO пропускаются), но в задании точность была не указана) Вы приняты на работу в маленькую мононациональную компанию)))

Спасибо)
Кстати, этот трюк был очень полезен, когда я писал роботов, котоыре одновременно разбирали задания из очереди типа

table Q (Id int primary key, Flag int, ...)
Flag = 0 — waiting to be executed
Flag = 1 — assigned to a robot,
Flag >= 2 — completed, failed etc.

Делалось атомарная выборка с захватом:

set rowcount 1
update Q set Id=Id,Flag=1 where Flag=0
Автор, а вы сами новичком не были? Когда о таких деталях узнали? До устройства на работу или вам дали шанс набраться опыта?

Интервью было не для джуниоров, а для людей, которые претендовали на много и писали 5-10 лет SQL, часто в финансовой или бухгалтерской сфере.


Если такой человек не может из одной таблицы выбрать данные за день, то извините, "свободная касса"

из одной таблицы выбрать данные за день


Так может так и стоило задачу сформулировать? А не накручивать? Конечно, дело ваше. Видимо много желающих на данную вакансию. Ее бы и джуниоры решили, если бы она была нормально сформулирована. Создаете сложность там, где ее нет. Это всего лишь SQL.

Сформулировать??? А что, из того SQL в задаче это не очевидно?

В условиях не дан тип данных поля DT. Это и есть главная неточность в этом примере. Может DT предполагает строку YYYY/MM/DD (мало ли чего разработчику системы взбрело в голову), тогда первый ответ SNAFU правильный. Какова задача, таково и решение.

По мне, единственное, что можно скзать на такую задачу:

Недостаточно данных для ответа на поставленные вопросы, так как неизвестен тип поля DT.

Если бы вы такое сказали, я бы ответил, что в проекте не все так плохо, и дата не хранится строкой, и уже явно сказал бы, что это datetime. А предположение зачлось бы в плюс.

Только полноправные пользователи могут оставлять комментарии. , пожалуйста.