Как конвертировать MMYYYY (042011) в дату и найти дату для текущей даты - PullRequest
0 голосов
/ 04 июня 2019

У меня есть столбец varchar с данными, подобными формату 042011 MMYYYY. Я хочу преобразовать это, чтобы найти разрыв от сегодняшней даты до этого столбца.

Я хочу получить ответ, например, 2,2 года или что-то связанное.

Я пробовал

SELECT datediff(month,FORMAT(GETDATE(),'MM') + FORMAT(GETDATE(),'yyyy'),'042011')

Ответы [ 6 ]

2 голосов
/ 04 июня 2019

MMYYYY не является датой, так как не содержит день месяца.Я подозреваю, что это строка, которая относится к конкретному отчетному периоду.

Типичным способом обработки таких периодов является использование календарной таблицы , например, с датами за 20 или 50 лет и дополнительными полями для года, месяца, дня месяца, номеров недели,названия месяцев и, что наиболее важно, периоды бизнес-отчетности.

В этой таблице значительно проще и быстрее сравнивать агрегированные данные за период или сравнивать разные периоды.Добавление индексов в различные столбцы столбцов для очень быстрых объединений и группировок по годам и т. Д.

Предполагается, что таблица календаря выглядит примерно так:

create table Calendar
(
    Date DATE NOT NULL PRIMARY KEY,
    Year int NOT NULL
    Month int not null,
    ....
    MonthLabel char(6),
    IX_Calendar_Year (Year),
    ....
    IX_Calendar_MonthLabel (MonthLabel),
)

Вы можете рассчитать, например, суммы замесяц с:

select Year,Month,SUM(Total) as Total
From Orders inner join Calendar 
    on Calendar.Date=Orders.Date
group by Year, Month

Работать с отчетными периодами так же просто:

select MonthLabel,SUM(Total) as Total
From Orders inner join Calendar 
    on Calendar.Date=Orders.Date
group by MonthLabel

Если исходные данные содержат метку отчетного периода, вы можете присоединиться к этому столбцу:

select MonthLabel,SUM(Total) as Total
From Orders inner join Calendar 
    on Calendar.MonthLabel=Orders.MonthLabel

Если метка исходит из пользовательского интерфейса, например, инструмента отчетности:

select Year,Month,SUM(Total) as Total
From Orders inner join Calendar 
    on Calendar.Date=Orders.Date
WHERE MonthLabel=@thatLabel
group by Year, Month

Все эти запросы быстрые , потому что они не включают синтаксический анализ и объединение, группирование,операции фильтрации используют индексированные столбцы

1 голос
/ 04 июня 2019

Вы хотите что-то подобное?

SELECT ROUND(CAST(DATEDIFF (month,CAST(RIGHT ('042011',4) + '-' + LEFT ('042011',2) + '-' + '01' AS DATE),CAST(GETDATE () AS DATE)) AS FLOAT) / CAST(12 AS FLOAT),2)

Результат: 8,2

Я установил для вашего столбца varchar значение dateformat (2011-04-01). Я добавляю день по умолчанию (1), затем получаю его timediff месяца для currentdate и делю месяц на 12, чтобы получить количество лет. Также сделано некоторое наложение и округление, чтобы получить желаемый результат.

0 голосов
/ 04 июня 2019

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

Попробуйте:

SELECT cast(datediff(year,CONVERT(DATETIME,'20110301',103),CONVERT(DATETIME,(FORMAT(GETDATE(),'yyyyMM')+'01'),103)) as varchar)+'.'+
cast((datediff(month,CONVERT(DATETIME,'20110301',103),CONVERT(DATETIME,(FORMAT(GETDATE(),'yyyyMM')+'01'),103)) -(datediff(year,CONVERT(DATETIME,'20110301',103),CONVERT(DATETIME,(FORMAT(GETDATE(),'yyyyMM')+'01'),103))*12)) as varchar)

или

Если вы хотите сделать это через функцию, тело будет выглядеть примерно так:

Declare @currentdate;
Declare @datetocompare varchar(10);
Declare @years varchar(10);
Declare @months varchar(10);

set @datetocompare='20110401';

set @currentdate=GETDATE();

select @years=datediff(year,CONVERT(DATETIME,@datetocompare,103),@currentdate);

select @months=datediff(month,CONVERT(DATETIME,@datetocompare,103),@currentdate)-(datediff(year,CONVERT(DATETIME,@datetocompare,103),@currentdate)*12);

select @years  +'.' +@months +' Years' asYearMonthDay;
0 голосов
/ 04 июня 2019

давайте построим этот шаг за шагом, чтобы вы могли следовать логике

declare @value varchar(6) = '042011'
declare @datestring varchar(8)
declare @date date

-- convert your format to a regional independant format including day 1
select @datestring = concat(right(@value, 4), left(@value, 2), '01')

-- convert this into a valid date type
select @date = convert(date, @datestring)

-- now we can get the difference, first the years and then the months
select  datediff(month, @date, getdate()) / 12 as years,
        datediff(month, @date, getdate()) % 12 as months

все вместе это выглядит так

select datediff(month, convert(date, (concat(right(@value, 4), left(@value, 2), '01'))), getdate()) / 12 as years,
       datediff(month, convert(date, (concat(right(@value, 4), left(@value, 2), '01'))), getdate()) % 12 as months

где @value можно заменить на столбец вашеготаблица

например, как это выглядит в запросе

declare @table table (value varchar(8))
insert into @table (value) 
values ('012011'), ('022011'), ('032011'), ('042011'), ('052011'), ('062011'), ('072011'), ('082011'), ('092011'), ('102011'), ('112011'), ('122011')

select value,
       datediff(month, convert(date, (concat(right(value, 4), left(value, 2), '01'))), getdate()) / 12 as years,
       datediff(month, convert(date, (concat(right(value, 4), left(value, 2), '01'))), getdate()) % 12 as months
from   @table

результат равен (getdate() returned 20190604 on the time of writing this)

value   years   months  
-----   -----   ------  
012011  8        5  
022011  8        4  
032011  8        3  
042011  8        2  
052011  8        1  
062011  8        0  
072011  7       11  
082011  7       10  
092011  7        9  
102011  7        8  
112011  7        7  
122011  7        6  
0 голосов
/ 04 июня 2019
SELECT DATEDIFF(
    month, 
    GETDATE(), 
    PARSE(
        CONCAT(
            RIGHT('042011', 4),'-',LEFT('042011', 2)) as date USING 'en-US'))

выход

-98

означает 98 месяцев назад

0 голосов
/ 04 июня 2019

Один из возможных подходов - следующий оператор.

Ввод:

CREATE TABLE #Dates (
    MmYyyy varchar(6)
)
INSERT INTO #Dates 
    (Mmyyyy)
VALUES
    ('042011'),
    ('052011'),
    ('062011')

T-SQL:

SELECT CONCAT(
    DATEDIFF(month,TRY_CONVERT(date, CONCAT(RIGHT(MmYyyy, 4), LEFT(MmYyyy, 2), '01')), GETDATE()) / 12, 
    ' y, ',
    DATEDIFF(month,TRY_CONVERT(date, CONCAT(RIGHT(MmYyyy, 4), LEFT(MmYyyy, 2), '01')), GETDATE()) % 12,
    ' m'
) AS [Difference]
FROM #Dates

Ввод:

Difference
8 y, 2 m
8 y, 1 m
8 y, 0 m

Примечания:

О «Я хочу получить ответ, как 2,2 года или что-то связанное» в вашем вопросе.Если вы хотите получить правильные результаты, расчет должен быть years and months, а не years and months / 12.Просто посмотрите следующий пример сценария - есть равные различия для 3 и 4 месяцев, а также для 9 и 10 месяцев.Округление до более чем одной десятичной позиции затрудняет понимание результата.

SELECT CONVERT(numeric(10, 1), v.Nmr / 12.0) AS [Difference]
FROM (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12)) v(Nmr)

Difference
0.1
0.2
0.3
0.3
0.4
0.5
0.6
0.7
0.8
0.8
0.9
1.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...