Рейтинг:
7
CHill60
В дополнение к вышеприведенному решению ОГА я предположил, что вы будете хранить Гражданский номер как ... номер, поэтому я придумал что-то вроде этого...
Получите дату рождения в формате xMMDD, разделив гражданский номер на 100000 (где x-1, 2 в соответствии с вашими правилами).
Преобразовать эту дату в формат CCYYMMDD путем добавления 17000000
Преобразуйте это число в реальную дату.
declare @demo table (id int identity (1,1), civicNo bigint, dob date)
insert into @demo (civicNo) values (286063001795),(260102901794)
update @demo set dob = CONVERT(datetime, convert(varchar(10), 17000000 + (civicNo / 100000)))
Как вы увидите из ссылки в решении 1, существует множество способов расчета возраста - я склонен использовать следующий метод, но имейте в виду, что я не тестировал его во всех комбинациях високосного года в год рождения, високосного года в "Сегодня", дня рождения и т. д.
select *, datediff(Month, dob, getdate())/12 as age, (civicNo / 100000),17000000 + (civicNo / 100000)
from @demo
Однако я полностью согласен с @OriginalGriff - не храните данные, которые являются динамическими в базе данных, вычисляйте их, когда это необходимо.
BillWoodruff
Ахой: магические числа зрячие :)
Maciej Los
Кэролайн, я не знаю, как ты это делаешь, но ты потрясающая, когда играешь с sql!
5ed!
el_tot93
братан как я могу сделать это с моей базой данных я новичок в кодировании и я стараюсь muny time
таблица ( табл. )
civicNo ( CIVILIDD )
доб ( доб )
CHill60
Как ты можешь делать что? Я не понимаю остальную часть вашего комментария - что такое tabl, CIVILDD или dob
el_tot93
у меня есть таблица с таким именем столбца
я пробую твой код, но не могу этого сделать
CHill60
Как насчёт
update tabl set dob = CONVERT(datetime, convert(varchar(10), 17000000 + (CIVILIDD / 100000)))
el_tot93
Преобразование типа данных varchar в тип данных datetime привело к значению вне диапазона.
Заявление было прекращено.
CHill60
столбец dob должен иметь тип date или datetime. Вы, очевидно, используете варчар. Всегда используйте соответствующий тип столбца для данных, которые вы собираетесь хранить в нем!
el_tot93
ок, я сделаю это спасибо большое бро спасибо за вашу помощь
el_tot93
как конвертировать float в bigint ?????????
CHill60
Либо отбросьте таблицу и воссоздайте ее с помощью bigint вместо float для CIVILIDD, либо вы можете использовать Приведение и преобразование (Transact-SQL) - SQL Server | Microsoft Docs[^]. Например (непроверенный)
CONVERT(bigint, CIVILIDD)
или
CAST(CIVILIDD AS bigint)
Лучше всего изменить схему таблицы, чтобы использовать правильные типы данных для столбцов
el_tot93
извините братан за то что он дал мне ту же ошибку мне нужно что то иметь потому что у меня много неправильных номеров CIVILD и дал мне ошибку потому что это
Преобразование не удалось при преобразовании даты и/или времени из символьной строки.
CHill60
Покажите мне свой сценарий создания таблицы и фактический запрос, который вы выполняете
el_tot93
я делаю это с ответом ответом
el_tot93
есть ли что-то неправильное в моем ответе
CHill60
Никогда не публикуйте вопросы или комментарии в качестве решений (ответов). Он будет опущен и предан забвению, а информация будет потеряна. Мне удалось захватить копию, но в будущем используйте ссылку "улучшить вопрос", чтобы добавить дополнительную информацию в свой список. вопрос
CHill60
Код, который вы разместили, работает. Об ошибках не сообщается.
el_tot93
Извини братан но у меня все еще есть та же ошибка msg я думаю потому что у меня неправильный Гражданский нет ?????? или это не проблема
CHill60
Какие данные дают вам ошибку?
Рейтинг:
21
OriginalGriff
Во - первых, создайте значение DATETIME- это довольно просто:
SELECT
Civil,
CONVERT(DATETIME,
CASE WHEN SUBSTRING(Civil, 1, 1) = 2 THEN '19' ELSE '20' END +
SUBSTRING(Civil, 2, 2) +
'/' + SUBSTRING(Civil, 4, 2) +
'/' + SUBSTRING(Civil, 6, 2),
120) AS DOB,
FROM MyTable
Теперь начинается самое трудное ... Возраст - это сложное понятие, потому что это не фиксированное значение, а относительное к текущей дате, и оно также имеет ряд компонентов.
Получить его относительно текущей даты не так уж сложно - GETDATE даст вам это, и вы легко сможете вычесть одно из другого. Проблема состоит из частей: x лет, y месяцев и z дней. Вам нужно будет рассчитать временной интервал, а затем разработать детали отдельно. Видеть здесь:
sql server - как рассчитать возраст (в годах) на основе даты рождения и getDate() - переполнение стека[
^] что дает решение.
- Я? Я бы вернул DOB из SQL, используя приведенный выше код, а затем обработал дату в C#, чтобы дать возраст:
Работа с возрастом: это не то же самое, что промежуток времени![
^]
На самом деле, нет, я бы не стал: я бы отказался от "гражданского" формата и сохранил DOB в значении DateTime, где его гораздо легче обрабатывать. "Гражданский" формат может быть сгенерирован из "реального" DOB довольно легко.
CHill60
- "Гражданский" формат может быть сгенерирован из" реального " DOB - только в том случае, если 01795 также был сохранен. Я полностью согласен с магазином доб, несмотря на возраст!
OriginalGriff
Я, наверное, хотел бы знать, что это кодирует - вероятно, время рождения? - и храните это в разумном формате, если это вообще уместно.
Но работа с "полузакодированными" значениями в SQL-это Пита и в лучшие времена ...
Maciej Los
Ты очень быстрый, пол!
5ed!
el_tot93
Тип данных аргумента float недопустим для аргумента 1 функции подстроки.
OriginalGriff
Вы храните гражданскую ценность в поплавке?
Ты сошел с ума.
Это значительно усложняет дело: вместо подстроки вам придется преобразовать значение FLOAT в INT, а затем использовать divide и modulus для извлечения каждой пары цифр / цифр перед построением значения DATETIME.
Серьезно, сбросьте его и используйте DOB в качестве даты-времени. С ним гораздо легче работать...
el_tot93
поэтому я преобразую столбец в int
OriginalGriff
Это решает одну часть - вам все равно придется играть с разделением и модулем каждый раз, когда вы его используете. Гораздо проще хранить значения даты и времени и генерировать свой "гражданский" номер только тогда, когда он вам действительно нужен, Честное слово!
Просто посмотрите, сколько людей здесь говорят: "измените способ хранения", вы думаете, что мы все ошибаемся? :смеяться:
CHill60
Если вы собираетесь сделать это таким образом то вам нужно будет использовать BigInt а не Int
OriginalGriff
Хорошая мысль - я забыл, что вы получите только 10 цифр в лучшем случае в INT.
Рейтинг:
14
Maciej Los
Если я вас хорошо понимаю, самое трудное для решения вашей проблемы-это "преобразовать" гражданский номер в дату.
Ну а MS SQL-Server 2017 имеет встроенную функцию, которая может возвращать дату из частей: DATEFROMPARTS (Transact-SQL) - SQL Server | Microsoft Docs[^]
Все, что вам нужно сделать, это передать правильные значения: год, месяц и день. Наконец, вы можете получить результат в годах, месяцах и т. д., Используя: DATEDIFF (Transact-SQL) - SQL Server | Microsoft Docs[^] функция.
--CivilNo to date parts:
SELECT CASE WHEN SUBSTRING(CivilNo, 1, 1) = '2' THEN 19 ELSE 20 END AS YearPart, CONVERT(INT, SUBSTRING(CivilNo, 2, 2)) AS MonthPart, CONVERT(INT, SUBSTRING(CivilNo, 4, 2)) AS DayPart
FROM YourTableName
Теперь вы знаете, как "конвертировать" Гражданский номер в части даты. Остальное принадлежит тебе! Удачи вам!
Для получения более подробной информации, пожалуйста, смотрите:
Подстрока (Transact-SQL) - SQL Server | Microsoft Docs[
^]
Приведение и преобразование (Transact-SQL) - SQL Server | Microsoft Docs[
^]
[Записка]: Кажется, у нас с оригиналом Гриффом одна и та же идея о преобразовании гражданского номера в дату, но я не так быстро печатаю и выражаю себя, как он!
el_tot93
Тип данных аргумента float недопустим для аргумента 1 функции подстроки.
Maciej Los
Спасибо, Билл.