#sql #ibm-midrange
#sql #ibm-средний уровень
Вопрос:
я работаю над старым AS400, который не поддерживает функцию SQL RIGHT (), и мне нужно выбирать строки на основе X крайних правых символов числа, длина которого может составлять 7 или 8 символов, используя SQL.
Как я могу получить то, что я хочу, если я не могу использовать RIGHT и не знаю точной длины числа?.
вот некоторый контекст на случай, если это окажется полезным:
Число является датой, но было сохранено как число, поэтому база данных удаляет первый ноль, в результате чего даты, начинающиеся с нуля, такие как 01032016 [читается как 01-03-2016], обрезаются до 1032016).
база данных довольно большая, поэтому запрос всех строк без фильтрации этого поля отнимает довольно много ресурсов и времени.
Изменение формата дат в базе данных на что-то более разумное вызвало бы критические изменения в программном обеспечении, которое я не поддерживаю, и это критически важно.
Комментарии:
1. поддерживает ли он SUBSTRING()?
Ответ №1:
Если данные были сохранены в виде числа, то база данных не удаляет начальные цифры. Любой инструмент, который вы используете для запроса данных, делает это.
Предполагая, что данные были сохранены в виде упакованной или разделенной на зоны десятичной дроби, а не целого числа (очень вероятно), затем используйте DIGITS()
для преобразования числа в фиксированный символ, включая начальные нули, а затем вы можете использовать SUBSTR()
Комментарии:
1. В итоге это был самый простой ответ на мою проблему, спасибо!.
Ответ №2:
SUBSTRING(mystr,character_length(mystr)-x 1,x)
или
SUBSTRING(mystr,character_length(mystr)-x 1)
Комментарии:
1. Это `character_length’ в DB2.
2. publib.boulder.ibm.com/iseries/v5r2/ic2924/index.htm?info/db2/…
3. Возможно, вы захотите обернуть все это в структуру регистра, которая гарантирует, что вы не вводите подстроку больше длины поля, хотя это может оказаться ненужным в зависимости от типа столбца, длины и других соображений кодирования.
4. Спасибо @TracyProbst, в целом вы правы. В данном конкретном случае мы знаем, что данные представляют собой «число, длина которого может составлять 7 или 8 символов»
5. К сожалению, character_length() также не поддерживается :/
Ответ №3:
Поддерживает ли он modulo?
Входные данные: 1032016
// Outputs: 2016
YOURDATEASINT % 10000 AS Year
MOD(YOURDATEASINT, 10000) AS Year
// Outputs: 32016
YOURDATEASINT % 1000000 AS MonthYear
MOD(YOURDATEASINT, 1000000) AS MonthYear
// Outputs: 1032016
YOURDATEASINT % 100000000 AS DayMonthYear
MOD(YOURDATEASINT, 100000000) AS DayMonthYear
Комментарии:
1. Привет, frumroll, к сожалению, мне нужно получить любую часть даты, это может быть год, год и месяц или год, месяц и день.
2. Вы все еще можете использовать MOD, просто измените 10000 по мере необходимости. Это эффективно работает так же, как и RIGHT, но только для чисел.
3. В конце концов, я решил использовать это, это обеспечило лучшую замену в моем случае использования.
4. есть ли вероятность, что этот метод очень медленный? я просматриваю 1,5 миллиона записей, и базе данных требуется 32 секунды, чтобы вернуть ответ.
Ответ №4:
Что меня поражает, так это то, что даты, сохраненные в виде чисел, даже не представлены в форме ГГГГММДД. Поэтому фильтрация по диапазону этих значений, охватывающему более одного года, особенно раздражает.
Единственное, что вы можете сделать, если у вас есть полномочия на создание таблиц и индексов, — это создать таблицу дат, в которой просто перечислены все возможные даты в некотором очень большом диапазоне. (150 000 записей охватывают более 400 лет, и по сегодняшним стандартам это небольшая таблица.) Эта таблица будет включать в себя несколько форматов, включая, по крайней мере, один, который является подлинным столбцом типа ДАТЫ, и тот, который вы пытаетесь обработать (в данном случае, 8-значное число, представляющее либо MMDDYYYY, либо DDMMYYYYY). Тогда вы можете использовать объединение, чтобы использовать возможности механизма запросов SQL, вместо того, чтобы выполнять вычисление функции для каждой строки данных (что и должно произойти, если вы преобразуете свои данные с использованием встроенного SQL).
Комментарии:
1. Спасибо за ваш вклад, но, к сожалению, я не думаю, что у меня есть такие полномочия, но я посмотрю, смогу ли я добиться, чтобы правильное форматирование в языках, говорящих на латинице (в данном случае в Аргентине), было ДД-ММ-ГГГГ в отличие от ГГГГ-ММ-ДД. Подробнее об этом можно прочитать здесь en.wikipedia.org/wiki/Date_format_by_country
2. Я знаком со всеми видами форматирования даты, но обычный способ обработки различного форматирования заключается в преобразовании «локального» формата в более удобный для вычислений формат хранения (если возможно, истинная ДАТА, иначе ГГГГММДД) в самый ранний возможный момент ввода и из формата хранения в локальный формат в самый поздний возможный момент вывода. Как MMDDYYYY, так и DDMMYYYYY ужасны для вычислений. На самом деле DDMMYYYY хуже всего, потому что вы даже не можете напрямую указать диапазон, охватывающий более одного месяца.
Ответ №5:
В то время как подстрока (цифры (date_column), x, y) является опцией, другой вариант представляет собой комбинацию функции MOD и разделения. Например, чтобы получить год, используйте это: SELECT MOD(date_column,10000)
, чтобы получить день, используйте это: CAST(MOD(date_column,1000000)/10000 AS INT)
, а чтобы получить месяц, используйте это: CAST(date_column/1000000 AS INT)
.