Получение количества недель в месяце из столбца Datetime - PullRequest
2 голосов
/ 19 сентября 2011

У меня есть таблица с именем FcData, и данные выглядят так:

Op_Date

2011-02-14 11:53:40.000
2011-02-17 16:02:19.000
2010-02-14 12:53:40.000
2010-02-17 14:02:19.000

Я рассчитываю получить количество недель в этом месяце от Op_Date.Поэтому я ищу вывод как:

 Op_Date                       Number of Weeks

    2011-02-14 11:53:40.000       5   
    2011-02-17 16:02:19.000       5
    2010-02-14 12:53:40.000       5
    2010-02-17 14:02:19.000       5

Ответы [ 7 ]

2 голосов
/ 19 сентября 2011

На этой странице есть несколько полезных функций для определения последнего дня любого месяца: http://www.sql -server-helper.com / functions / get-last-day-of-month.aspx

Просто оберните вывод этой функции вызовом DATEPART(wk, last_day_of_month).Комбинируя его с эквивалентным вызовом для 1-го дня недели, вы получите количество недель в этом месяце.

1 голос
/ 19 сентября 2011

Вот мое мнение, возможно, что-то пропустил.

В Linq:

from u in TblUsers
let date = u.CreateDate.Value
let firstDay = new DateTime(date.Year, date.Month, 1)
let lastDay = firstDay.AddMonths(1)
where u.CreateDate.HasValue
select Math.Ceiling((lastDay - firstDay).TotalDays / 7)

И сгенерированный SQL:

-- Region Parameters
DECLARE @p0 Int = 1
DECLARE @p1 Int = 1
DECLARE @p2 Float = 7
-- EndRegion
SELECT CEILING(((CONVERT(Float,CONVERT(BigInt,(((CONVERT(BigInt,DATEDIFF(DAY, [t3].[value], [t3].[value2]))) * 86400000) + DATEDIFF(MILLISECOND, DATEADD(DAY, DATEDIFF(DAY, [t3].[value], [t3].[value2]), [t3].[value]), [t3].[value2])) * 10000))) / 864000000000) / @p2) AS [value]
FROM (
    SELECT [t2].[createDate], [t2].[value], DATEADD(MONTH, @p1, [t2].[value]) AS [value2]
    FROM (
        SELECT [t1].[createDate], CONVERT(DATETIME, CONVERT(NCHAR(2), DATEPART(Month, [t1].[value])) + ('/' + (CONVERT(NCHAR(2), @p0) + ('/' + CONVERT(NCHAR(4), DATEPART(Year, [t1].[value]))))), 101) AS [value]
        FROM (
            SELECT [t0].[createDate], [t0].[createDate] AS [value]
            FROM [tblUser] AS [t0]
            ) AS [t1]
        ) AS [t2]
    ) AS [t3]
WHERE [t3].[createDate] IS NOT NULL
1 голос
/ 19 сентября 2011

Используйте это, чтобы получить номер недели для ОДНОЙ конкретной даты. Замените GetDate() на вашу дату:

declare @dt date = cast(GetDate() as date);
declare @dtstart date =  DATEADD(day, -DATEPART(day, @dt) + 1, @dt);
declare @dtend date = dateadd(DAY, -1, DATEADD(MONTH, 1, @dtstart));

WITH dates AS (
     SELECT @dtstart ADate
     UNION ALL
     SELECT DATEADD(day, 1, t.ADate) 
       FROM dates t
      WHERE DATEADD(day, 1, t.ADate) <= @dtend
)
SELECT top 1 DatePart(WEEKDAY, ADate) weekday, COUNT(*) weeks
  FROM dates d
  group by DatePart(WEEKDAY, ADate)
  order by 2 desc

Объяснено: CTE создает результирующий набор со всеми датами месяца данной даты. Затем мы запрашиваем набор результатов, группируя по дням недели и подсчитываем количество вхождений. Максимальное число даст нам количество недель, на которые перекрывается месяц (предпосылка: если в месяце 5 понедельников, он будет охватывать пять недель в году).

Обновление

Теперь, если у вас есть несколько дат, вы должны соответствующим образом настроить их, объединив запрос с dates CTE.

0 голосов
/ 23 сентября 2014

Вот как вы можете получить точное количество недель:

DECLARE @date DATETIME
SET @date = GETDATE()
SELECT ROUND(cast(datediff(day, dateadd(day, 1-day(@date), @date), dateadd(month, 1, dateadd(day, 1-day(@date), @date))) AS FLOAT) / 7, 2)

С этим кодом для сентябрь 2014 вы получите 4,29 , что на самом деле верно, так какосталось 4 полных недели и еще 2 дня.

0 голосов
/ 25 июня 2012

Количество недель в месяце можно получить, используя следующий метод.

Datepart(WEEK,
         DATEADD(DAY,
                 -1,
                 DATEADD(MONTH,
                         1,
                         DATEADD(DAY,
                                 1 - DAY(GETDATE()),
                                 GETDATE())))
         -
         DATEADD(DAY,
                 1 - DAY(GETDATE()),
                 GETDATE())
         +1
         )
0 голосов
/ 20 сентября 2011

Могут быть разные подходы к реализации идеи , предложенной @Marc B .Вот один из тех случаев, когда пользовательские функции не используются, но первый и последний дни месяца рассчитываются напрямую:

WITH SampleData AS (
  SELECT CAST('20110214' AS datetime) AS Op_Date
  UNION ALL SELECT '20110217'
  UNION ALL SELECT '20100214'
  UNION ALL SELECT '20100217'
  UNION ALL SELECT '20090214'
  UNION ALL SELECT '20090217'
),
MonthStarts AS (
  SELECT
    Op_Date,
    MonthStart = DATEADD(DAY, 1 - DAY(Op_Date), Op_Date)
    /* alternatively: DATEADD(MONTH, DATEDIFF(MONTH, 0, Op_Date), 0) */
  FROM FcData
),
Months AS (
  SELECT
    Op_Date,
    MonthStart,
    MonthEnd = DATEADD(DAY, -1, DATEADD(MONTH, 1, MonthStart))
  FROM FcData
)
Weeks AS (
  SELECT
    Op_Date,
    StartWeek = DATEPART(WEEK, MonthStart),
    EndWeek   = DATEPART(WEEK, MonthEnd)
  FROM MonthStarts
)
SELECT
  Op_Date,
  NumberOfWeeks = EndWeek - StartWeek + 1
FROM Weeks

Все вычисления могут быть выполнены за один SELECT, но я решил разбить их на шаги и размещать каждыйшаг в отдельном CTE, чтобы лучше видеть, как был получен конечный результат.

0 голосов
/ 19 сентября 2011

Согласно этой статье MSDN: http://msdn.microsoft.com/en-us/library/ms174420.aspx вы можете получить только текущую неделю в году, а не то, что возвращает этот месяц.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...