Неделя_месяца = текущая_неделя_года - последняя_неделя_пмЭто все было бы хорошо, если бы не одно но. Новый месяц почти всегда начинается посередине недели. И если прошлый месяц закончился на 22-ой неделе, то текущий месяц имеет неплохие шансы начаться тоже с 22-ой недели. Если начнем вычитать то получим месяцы начиная с нулевого (22 — 22), 0,1,2… непорядок. Надо бы, как нибудь сделать, чтобы если неделя на которую закончился старый месяц и начался новый совпадают, то к числу недель прибавить единичку. Воспользуемся возможностями деления. Если делить целые (int), то результат деления тоже будет целым числом, а дробная часть будет отброшена. Таким образом
Неделя_месяца = текущая_неделя_года + (последняя_неделя_пм/первая_неделя_тм - последняя_неделя_пм)Теперь нумерация недель месяца будет начинаться правильно, с единицы, а не с нуля. Всё? Ещё нет. Мы упустили из виду первый месяц года, то есть январь. Если мы из его первой недели станем вычитать последнюю неделю, предыдущего месяца, то есть последнюю неделю декабря прошлого года, то -52 (1 — 53) это не совсем то что нам нужно. Обычно чтобы избавиться от неугодного числа его умножат на ноль. Поступим так же. Сделаем так что если месяц первый то число которое нужно отнять от его недель умножается на 0, а если месяц не первый, то на 1. Интересно, как можно превратить единицу в ноль, а все остальные числа, которое больше единицы, в единицу. Здесь нам тоже поможет деление целых чисел, в придачу с возведением в степень. Вот так:
2 - 21/XТеперь уравнение по нахождению недели месяца будет выглядеть так:
Неделя_месяца = текущая_неделя_года + (последняя_неделя_пм/первая_неделя_тм - последняя_неделя_пм)х(2 - 21/номер_месяца)Переведем все это на язык Transact SQL
Номер текущей недели: DATEPART(wk, @dt)
Номер первой недели текущего месяца: DATEPART(wk, DATEADD(MONTH, MONTH(@dt)-1, convert(date,DATENAME(yy, @dt))))
Номер последней недели прошлого месяца: DATEPART(wk, DATEADD(DAY, -1, DATEADD(MONTH, MONTH(@dt)-1, convert(date,DATENAME(yy, @dt)))))
Получим такое громоздкое выражение:
DATEPART(wk, @dt) + (DATEPART(wk, DATEADD(DAY, -1, DATEADD(MONTH, MONTH(@dt)-1, convert(date,DATENAME(yy, @dt)))))/DATEPART(wk,
DATEADD(MONTH, MONTH(@dt)-1, convert(date,DATENAME(yy, @dt)))) - DATEPART(wk, DATEADD(DAY, -1, DATEADD(MONTH, MONTH(@dt)-1,
convert(date,DATENAME(yy, @dt))))))*(2 - POWER(2, 1/MONTH(@dt))) Если в переменной @dt находится дата, то это выражение возвращает неделю месяца (от 1 до 6) к которой эта дата относится. Впрочем это слишком громоздкий способ. На просторах сети встречаются варианты гораздо короче и элегантнее. Например такой:
DATEPART(week, @dt) - DATEPART(week, DATEADD(month, DATEDIFF(month, 0, @dt), 0))+1. Вроде бы работает.

