По типичным, ОП не дал своего DDL.
FWiW, может быть большое преимущество в хранении отдельных компонентов дат, , если, большинство запросов зависит от этих компонентов и индексируются; хотя с дополнительной возможностью производного INDEX выражения, такие как YEAR (date_field) или SUBSTR (mmddyyyy_string_field, 5, 4) в качестве ключа, могут улучшить проблемы с выводами времени выполнения, для которых они выполняются. Преобразование в описанный INVDAT в выбранном формате - это не все, что хорошее выбора ИМО, даже если большинство из них не соответствуют конкретным компонентам даты; Я прокомментирую это позже.
Хотя можно было бы ожидать, что принятый ответ должен дать в целом правильные результаты из-за ожиданий о том, что область данных, являющихся явными значениями даты, по меньшей мере, одной цифрой [строка или числовая], результаты вполне зависят от данные-типирование; что за «начальные нули ... в настоящее время не хранятся» в старых значениях, тип данных является явно символьной строкой vs числовой, а для «(опять же, в char)» можно ожидать CHAR vs VARCHAR. И как строковые данные, нет упоминания о том, можно ли отрегулировать ненулевые запаздывающие \ добавленные сохраненные значения с помощью корректировки вправо или с правой стороны.
Это и другие \ будущих ответов и комментарии могут не подходить для фактического и неизвестного \ неустановленного DDL, и, таким образом, эти ответы должны быть предисловием эффективного «с этим DDL как данных»; но также и для типичных респондентов редко будут предлагать это пояснение :-(
Например, скаляр Left Pad (LPAD) [доступен с IBM DB2 for i 7.1], который уже упоминался в комментарии. более заметный соответствующий скалярный запрос для предполагаемого эффекта, чем использование более длинного существующего и вполне способного RIGHT-скаляра [в сочетании с добавлением строки из одного или нескольких нулей, что необходимо для фактических данных, которые также были оставлены в OP, но, безусловно, действительный только при объединении с лишенным значения], LPAD, вероятно, также не сработает для OP, потому что их исходные данные, скорее всего, CHAR [per "(опять же, char)"], а не VARCHAR , т.е. LPAD не соответствует здравому смыслу , за неудачу в реализации наиболее вероятных \ рациональных намерений и вместо этого работает как не более чем эффективная подстрока по данным CHAR фиксированной длины, несмотря на то, что функция SUBSTR уже давно существует для этого эффекта.
Конечно, с теми же выводами о том, что OP имеет для DDL, даже выражение RIGHT('00' CONCAT char_2_field, 2)
не дает желаемых результатов; например с измененным по левому краю значением '1 '
в поле, это выражение эффективно запрашивает RIGHT(CHAR('001 ', 4), 2)
, для которого результат '1 '
, а не предполагаемый желаемый '01'
и с правильным значением ' 1'
в поле, это выражение эффективно запрашивая RIGHT(CHAR('00 1', 4), 2)
, для которого результат ' 1'
, а не предполагаемый желаемый '01'
. Я был на самом деле немного удивлен, что ответил; т. е. я был потрясен тем, что, по-видимому, исходный DDL имел поля, объявленные как VARCHAR, и что эти значения, по-видимому, также были правильно удалены, когда они были сохранены или надлежащим образом отброшены как таковые, откуда они пришли.
Если эти поля были VARCHAR или были выполнены STRIP [или LTRIM или аналогичными] для осуществления ввода данных различной строки [по-видимому, необязательно с левым урезанным результатом в соответствии с последствиями документов для эффекта LPAD, но мой опыт предполагает, что рекомендуется использовать левую или полностью зачистку], тогда строка может быть сгенерирована, как ожидалось, для выражений, предлагаемых как в ответе , так и в комментарии .
Скаляр DATE, отмеченный в комментарии, может быть опущен, и порядок компонентов даты может быть переупорядочен. Но в качестве строки вместо результата ввода данных DATE строка, отформатированная как MMDDYYYY, показанная в OP , нехорошо упорядоченная [лишена лексикографического качества], поэтому бесполезна при сортировке и селективности для чего угодно, кроме [ не] равные предикаты; строка, форматированная как YYYYMMDD [почти как то, что этот комментарий пытается предложить] :хорошо упорядоченный, поэтому он хорошо подходит для сортировки и для относительной [а не только совпадения | несовпадения] избирательности; не имея неотъемлемой поддержки для арифметики DATE и валидации, является меньшим отрицательным.
Примечание: следующие сценарии действий для DDL и заполняющих данных предполагают, что «cc» относится к простым двузначным значениям счетного века; т.е. «cc» игнорирует нулевой век, так что «19» подразумевает 1900-е годы, а не 1800-е, и такое, что «cc» не является альтернативным отображением таких «00» -> 19, 01 '-> 20' , и т.д..
Установки для обеспечения тестирования данных и альтернативных запросов:
create table old_table
(month char(2) not null with default
, oedy01 char(2) not null with default
, oecc01 char(2) not null with default
, oeyr01 char(2) not null with default
)
;
create table new_table
(invdat char(8) not null with default
)
;
insert into old_table /* mm, dd, cc, yy */ values
(' 1', ' 1', '19', '40'), ('3 ', '3 ', '19', '40')
, (' 1', ' 1', '20', ' 0'), ('3 ', '3 ', '20', '0 ')
, (' 2', ' 2', '20', ' '), ('4 ', '4 ', '20', ' ')
, (' 1', ' 1', '20', ' 1'), ('3 ', '3 ', '20', '1 ')
, (' 1', ' 1', '20', '39'), ('3 ', '3 ', '20', '39')
, (' 1', ' 1', ' 0', ' 1'), ('3 ', '3 ', '0 ', '1 ')
, (' 2', ' 2', ' ', ' 1'), ('4 ', '4 ', ' ', '1 ')
; -- mm(1,2):right-adj, mm(3,4):left-adj, mm(2,4):blank-elems
-- 14 rows inserted in OLD_TABLE
Теперь для запросов, что была установка выше:
SELECT Right('00'||month, 2) || Right('00'||oedy01, 2)
|| Right('00'||oecc01, 2) || Right('00'||oeyr01, 2) as invdat
from old_table
where month not in (2, 4)
; -- report of above query follows; no leading zeroes anywhere:
INVDAT
1 11940
3 3 1940
1 120 0
3 3 200
1 120 1
3 3 201
1 12039
3 3 2039
1 1 0 1
3 3 0 1
-- end of data --
select
lpad(month , 2, '0') concat lpad(oedy01, 2, '0') concat
lpad(oecc01 , 2, '0') concat lpad(oeyr01, 2, '0') as invdat
from old_table
where month not in (2, 4)
; -- report of above query follows; no leading zeroes anywhere:
INVDAT
1 11940
3 3 1940
1 120 0
3 3 200
1 120 1
3 3 201
1 12039
3 3 2039
1 1 0 1
3 3 0 1
-- end of data; a duplicate of the prior query report --
Так что с данной настройкой, указанные запросы не являются очень полезно. С несовершеннолетним пересмотр каждого запроса, чтобы обеспечить данные CHAR сначала раздели лишних пробелов, результаты намного лучше:
select
lpad(strip( month) , 2, '0') concat
lpad(strip( oedy01) , 2, '0') concat
lpad(strip( oecc01) , 2, '0') concat
lpad(strip( oeyr01) , 2, '0') as invdat
from old_table
/* where month not in (2, 4) -- this *fixes* blank values too */
; -- report of above query follows; expected leading zeroes appear:
INVDAT
01011940
03031940
01012000
03032000
02022000
04042000
01012001
03032001
01012039
03032039
01010001
03030001
02020001
04040001
-- end of data --
SELECT
Right('00' concat strip(month) , 2) concat
Right('00' concat strip(oedy01) , 2) concat
Right('00' concat strip(oecc01) , 2) concat
Right('00' concat strip(oeyr01) , 2) as invdat
from old_table
/* where month not in (2, 4) -- this *fixes* blank values too */
; -- report of above query matches the prior; not repeated here
Если DDL были вместо числовых и известно, имеют действительные данные десятичные, сохраненные для значений, то следующий может быть представитель сценария:
drop table old_table
;
create table old_table
(month dec (2) not null with default
, oedy01 dec (2) not null with default
, oecc01 dec (2) not null with default
, oeyr01 dec (2) not null with default
)
;
insert into old_table /* mm, dd, cc, yy */ values
(' 1', ' 1', '19', '40'), ('3 ', '3 ', '19', '40')
, (' 1', ' 1', '20', ' 0'), ('3 ', '3 ', '20', '0 ')
, (' 1', ' 1', '20', ' 1'), ('3 ', '3 ', '20', '1 ')
, (' 1', ' 1', '20', '39'), ('3 ', '3 ', '20', '39')
, (' 1', ' 1', ' 0', ' 1'), ('3 ', '3 ', '0 ', '1 ')
; -- notably, no blank values per inability to cast to decimal
select
digits(month) concat digits(oedy01) concat
digits(oecc01) concat digits(oeyr01) as invdat
from old_table
; -- report from above query follows; DIGITS casting gives leading zeros:
INVDAT
01011940
03031940
01012000
03032000
01012001
03032001
01012039
03032039
01010001
03030001
-- end of data --
Оба запросов предложенных [вариантов, которые я включил в моих примерах выше; один с выражением RIGHT(), и тот, который имеет LPAD()] из ответа и в комментарии , даст тот же отчет, что и выше. Это связано с тем, что результатом неявного переноса из CHAR в DECIMAL является измененное по левому краю переменное символьное строковое представление числового значения и, следовательно, неявно левая и изменяемая длина, поэтому эти скалярные функции будут давать желаемый результат.
Если вышеописанный скрипт для использования числовых типов данных [вместо «ссылались весь полукокс» типов данных] является причиной ответа выбран ОРОМ как приемлемые, то, что служит, чтобы подчеркнуть, как poorly- объяснил сценарий проблемы, и подразумевает, насколько легко это могло быть предотвращено, включив DDL; и лучше, чтобы дополнительно включить образцы данных.
Первый вопрос: почему части даты хранятся как отдельные строки, а не одна дата? Второй вопрос - почему вы хотите построить из него строку, а не дату? Гораздо проще работать с датами при использовании типа даты. –
В любом случае, вот как левые ноты для строки: http://stackoverflow.com/questions/4964244/pad-varchar-numbers-with-0s-in-db2 –
Я бы попробовал некоторое обучение клиентов на вот этот. Даты сохраняются в «слое данных», пока они отображаются на «уровне представления». Уровень данных и формат, в котором они хранятся, не имеют никакого значения, когда дело доходит до отображения и заполнения. Echo of Thorsten, переключение на поля даты ... вы в настоящее время настраиваете полный беспорядок для своего клиента, чтобы иметь дело в более позднее время. – Twelfth