Jak określić liczbę dni w miesiącu w SQL Server?

97

Muszę określić liczbę dni w miesiącu dla danego dnia w SQL Server.

Czy jest wbudowana funkcja? Jeśli nie, czego należy użyć jako funkcji zdefiniowanej przez użytkownika?

Nawet Mien
źródło

Odpowiedzi:

116

W pierwszym dniu podanego miesiąca możesz użyć:

datediff(day, @date, dateadd(month, 1, @date))

Aby działało na każdą randkę:

datediff(day, dateadd(day, 1-day(@date), @date),
              dateadd(month, 1, dateadd(day, 1-day(@date), @date)))
Mehrdad Afshari
źródło
2
Jak mówi Stan, w niektórych przypadkach da to niedokładne wyniki
DJ.
3
czy nie masz na myśli: datediff (day, dateadd (day, 1-day (@date), @date), dateadd (month, 1, dateadd (day, 1-day (@date), @date)))
feihtthief
3
To rzadki przypadek narożny, ale właśnie się z nim natknąłem: spowoduje to błąd w grudniu 9999.
Heinzi,
1
To nie działa dla żadnej daty w grudniu 9999. Otrzymujesz przepełnienie typu daty. To zadziałało dla mnie w SQL Server 2014: case when datediff(m, dateadd(day, 1-day(@date), @date), convert(date, convert(datetime, 2958463))) > 0 then datediff(day, dateadd(day, 1-day(@date), @date), dateadd(month, 1, dateadd(day, 1-day(@date), @date))) else 31 end
bradwilder31415
2
Wszystkie wymienione tutaj rozwiązania bledną w porównaniu z elegancją odpowiedzi @Mikael Eriksson . Działa to zawsze, gdy podana jest prawidłowa data bez szalonych obejść dla przypadków niszowych i jest znacznie prostszym kodem - gorąco polecam każdemu, kto korzysta z T-SQL Stick, aby uzyskać daykomponent eomonthwyniku.
bsplosion
152

W SQL Server 2012 możesz użyć EOMONTH (Transact-SQL), aby uzyskać ostatni dzień miesiąca, a następnie możesz użyć DAY (Transact-SQL), aby uzyskać liczbę dni w miesiącu.

DECLARE @ADate DATETIME

SET @ADate = GETDATE()

SELECT DAY(EOMONTH(@ADate)) AS DaysInMonth
Mikael Eriksson
źródło
1
A jeśli potrzebujesz liczby dni w danym, możesz również użyć metody DATEFROMPARTS. Powyższy kod stałby się SELECT DAY (EOMONTH (DATEFROMPARTS (@year, @month, 1))) AS DaysInMonth
nmariot
Piękno tego rozwiązania wchodzi w grę, jeśli @ADate jest złożoną wartością obliczoną! +1
Stefan Steiger
Bardzo Ci dziękuję!
Rejwanul Reja
28

Najbardziej eleganckie rozwiązanie: działa dla każdego @DATE

DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,@DATE),0)))

Wrzuć to do funkcji lub po prostu użyj w tekście. To odpowiada na pierwotne pytanie bez dodatkowych śmieci w innych odpowiedziach.

przykłady dat z innych odpowiedzi:

SELECT DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,'1/31/2009'),0))) Zwraca wartość 31

SELECT DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,'2404-feb-15'),0))) Zwraca wartość 29

SELECT DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,'2011-12-22'),0))) Zwraca wartość 31

Daniel Davis
źródło
23

O wiele prostsze ... spróbuj day(eomonth(@Date))

Javier
źródło
1
Myślę, że twoja odpowiedź jest najlepsza, tak prosta. Dzięki!
Ofear,
12
--Last Day of Previous Month
SELECT DATEPART(day, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)))

--Last Day of Current Month
SELECT DATEPART(day, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0)))

--Last Day of Next Month
SELECT DATEPART(day, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+2,0)))

Osobiście jednak zrobiłbym dla niego UDF, gdyby nie było wbudowanej funkcji ...

Brimstedt
źródło
5

Sugerowałbym:

SELECT DAY(EOMONTH(GETDATE()))
gvschijndel
źródło
datepart nie zwraca liczby dni, a twoja odpowiedź również jest błędna
TheGameiswar
U mnie zadziałało, ale z pewnością użycie funkcji dnia byłoby bardziej
przejrzystą
2
ta odpowiedź jest prawie identyczna z tą poniżej, przy głosach 75.
Hila DG
3

Ten kod podaje liczbę dni w bieżącym miesiącu:

SELECT datediff(dd,getdate(),dateadd(mm,1,getdate())) as datas

Zmień getdate()datę, do której chcesz liczyć dni.

Prashant
źródło
2
   --- sql server below 2012---
    select day( dateadd(day,-1,dateadd(month, 1, convert(date,'2019-03-01'))))
    -- this for sql server 2012--
    select day(EOMONTH(getdate()))
Saikh Rakif
źródło
1

Rozwiązanie 1: Znajdź liczbę dni w miesiącu, w którym aktualnie jesteśmy

DECLARE @dt datetime
SET     @dt = getdate()

SELECT @dt AS [DateTime],
       DAY(DATEADD(mm, DATEDIFF(mm, -1, @dt), -1)) AS [Days in Month]

Rozwiązanie 2: Znajdź liczbę dni w podanej kombinacji miesiąc-rok

DECLARE @y int, @m int
SET     @y = 2012
SET     @m = 2

SELECT @y AS [Year],
       @m AS [Month],
       DATEDIFF(DAY,
                DATEADD(DAY, 0, DATEADD(m, ((@y - 1900) * 12) + @m - 1, 0)),
                DATEADD(DAY, 0, DATEADD(m, ((@y - 1900) * 12) + @m, 0))
               ) AS [Days in Month]
Phillip Copley
źródło
1

Musisz dodać funkcję, ale jest to prosta funkcja. Używam tego:

CREATE FUNCTION [dbo].[ufn_GetDaysInMonth] ( @pDate    DATETIME )

RETURNS INT
AS
BEGIN

    SET @pDate = CONVERT(VARCHAR(10), @pDate, 101)
    SET @pDate = @pDate - DAY(@pDate) + 1

    RETURN DATEDIFF(DD, @pDate, DATEADD(MM, 1, @pDate))
END

GO
Himanshu Jansari
źródło
1
Nawiasem mówiąc, połączenie DATEDIFF i DATEADD nie zawsze działa. Jeśli umieścisz w nim datę 31.01.2009, DATEADD zwróci 2/28/2009, a DATEDIFF da 28 zamiast 31.
jak sprawdzić, to znaczy co wykonać żeby sprawdzić dni w miesiącu ??
hud
1
SELECT Datediff(day,
(Convert(DateTime,Convert(varchar(2),Month(getdate()))+'/01/'+Convert(varchar(4),Year(getdate())))),
(Convert(DateTime,Convert(varchar(2),Month(getdate())+1)+'/01/'+Convert(varchar(4),Year(getdate()))))) as [No.of Days in a Month]
Vignesh Anandaraj
źródło
1
select  datediff(day, 
        dateadd(day, 0, dateadd(month, ((2013 - 1900) * 12) + 3 - 1, 0)),
        dateadd(day, 0, dateadd(month, ((2013  - 1900) * 12) + 3, 0))
        )

Ładny Prosty i nie wymaga tworzenia żadnych funkcji Działa dobrze

pradeep
źródło
1

Musisz stworzyć funkcję, ale zrobisz to dla własnej wygody. Działa idealnie i nigdy nie napotkałem żadnych błędnych obliczeń przy użyciu tej funkcji.

CREATE FUNCTION [dbo].[get_days](@date datetime)
RETURNS int
AS
BEGIN
    SET @date = DATEADD(MONTH, 1, @date)
    DECLARE @result int = (select DAY(DATEADD(DAY, -DAY(@date), @date)))
    RETURN @result
END

Jak to działa: odjęcie numeru dnia daty od daty daje ostatni dzień poprzedniego miesiąca. Musisz więc dodać jeden miesiąc do podanej daty, odjąć numer dnia i uzyskać składnik dnia w wyniku.

an40us
źródło
1
select add_months(trunc(sysdate,'MM'),1) -  trunc(sysdate,'MM') from dual;
kritika
źródło
0

Głosowałem za Mehrdadem, ale to też działa. :)

CREATE function dbo.IsLeapYear
(
    @TestYear int
)
RETURNS bit
AS
BEGIN
    declare @Result bit
    set @Result = 
    cast(
        case when ((@TestYear % 4 = 0) and (@testYear % 100 != 0)) or (@TestYear % 400 = 0)
        then 1
        else 0
        end
    as bit )
    return @Result
END
GO

CREATE FUNCTION dbo.GetDaysInMonth
(
    @TestDT datetime
)
RETURNS INT
AS
BEGIN

    DECLARE @Result int 
    DECLARE @MonthNo int

    Set @MonthNo = datepart(m,@TestDT)

    Set @Result = 
    case @MonthNo
        when  1 then 31
        when  2 then 
            case 
                when dbo.IsLeapYear(datepart(yyyy,@TestDT)) = 0
                then 28
                else 29
            end
        when  3 then 31
        when  4 then 30
        when  5 then 31
        when  6 then 30
        when  7 then 31
        when  8 then 31
        when  9 then 30 
        when 10 then 31
        when 11 then 30 
        when 12 then 31
    end

    RETURN @Result
END
GO

Testować

declare @testDT datetime;

set @testDT = '2404-feb-15';

select dbo.GetDaysInMonth(@testDT)
złodziejaszek
źródło
0

Oto kolejny...

Select Day(DateAdd(day, -Day(DateAdd(month, 1, getdate())), 
                         DateAdd(month, 1, getdate())))
Charles Bretana
źródło
0

Wiem, że to pytanie jest stare, ale pomyślałem, że podzielę się tym, czego używam.

DECLARE @date date = '2011-12-22'

/* FindFirstDayOfMonth - Find the first date of any month */
-- Replace the day part with -01
DECLARE @firstDayOfMonth date = CAST( CAST(YEAR(@date) AS varchar(4)) + '-' + 
                                      CAST(MONTH(@date) AS varchar(2)) + '-01' AS date)
SELECT @firstDayOfMonth

i

DECLARE @date date = '2011-12-22'

/* FindLastDayOfMonth - Find what is the last day of a month - Leap year is handled by DATEADD */
-- Get the first day of next month and remove a day from it using DATEADD
DECLARE @lastDayOfMonth date = CAST( DATEADD(dd, -1, DATEADD(mm, 1, FindFirstDayOfMonth(@date))) AS date)

SELECT @lastDayOfMonth

Można je połączyć, aby utworzyć jedną funkcję, aby w razie potrzeby pobrać liczbę dni w miesiącu.

DanielM
źródło
0
SELECT DAY(SUBDATE(ADDDATE(CONCAT(YEAR(NOW()), '-', MONTH(NOW()), '-1'), INTERVAL 1 MONTH), INTERVAL 1 DAY))

Nice 'n' Simple i nie wymaga tworzenia żadnych funkcji

Paweł
źródło
To jest dla SQL Server; Nigdy nie słyszałem o subdatefunkcji.
LittleBobbyTables - Au Revoir
0

Odpowiedź Mehrdada Afshariego jest najdokładniejsza, poza zwykłą odpowiedzią jest ona oparta na formalnym podejściu matematycznym podanym przez Curtisa McEnroe na jego blogu https://cmcenroe.me/2014/12/05/days-in-month-formula.html

DECLARE @date  DATE= '2015-02-01'
DECLARE @monthNumber TINYINT 
DECLARE @dayCount TINYINT
SET @monthNumber = DATEPART(MONTH,@date )
SET @dayCount = 28 + (@monthNumber + floor(@monthNumber/8)) % 2 + 2 %    @monthNumber + 2 * floor(1/@monthNumber)   
SELECT @dayCount + CASE WHEN @dayCount = 28 AND DATEPART(YEAR,@date)%4 =0 THEN 1 ELSE 0 END -- leap year adjustment
AbhishekT
źródło
0

Aby uzyskać nie. dni w miesiącu możemy bezpośrednio skorzystać z Day () dostępnego w SQL.

Skorzystaj z łącza zamieszczonego na końcu mojej odpowiedzi dotyczącej programu SQL Server 2005/2008.

Poniższy przykład i wynik pochodzą z SQL 2012

alter function dbo.[daysinm]
(
@dates nvarchar(12)
)
returns int
as
begin
Declare @dates2 nvarchar(12)
Declare @days int
begin
select @dates2 = (select DAY(EOMONTH(convert(datetime,@dates,103))))
set @days = convert(int,@dates2)
end
return @days
end

--select dbo.daysinm('08/12/2016')

Wynik w programie SQL Server SSMS

  (no column name)
1 31

Proces:

Kiedy używany jest EOMONTH, niezależnie od używanego przez nas formatu daty jest konwertowany na format DateTime serwera SQL. Wtedy data wyjściowa EOMONTH () będzie 2016-12-31, z 2016 jako rok, 12 jako miesiąc i 31 jako dni. Ten wynik po przekazaniu do Day () daje całkowitą liczbę dni w miesiącu.

Jeśli chcemy uzyskać natychmiastowy wynik do sprawdzenia, możemy bezpośrednio uruchomić poniższy kod,

select DAY(EOMONTH(convert(datetime,'08/12/2016',103)))

lub

select DAY(EOMONTH(convert(datetime,getdate(),103)))

w celu odniesienia się do pracy w SQL Server 2005/2008/2012, skorzystaj z następującego łącza zewnętrznego ...

Znajdź liczbę dni w miesiącu w języku SQL

VSV AdityaSarma
źródło
0
DECLARE @date DATETIME = GETDATE(); --or '12/1/2018' (month/day/year) 
SELECT DAY(EOMONTH ( @date )) AS 'This Month'; 
SELECT DAY(EOMONTH ( @date, 1 )) AS 'Next Month';

wynik: w tym miesiącu 31

W przyszłym miesiącu 30

ardem
źródło
to nie zwraca liczby dni w miesiącu
ashleedawg
Tak. Ale tylko dla SQL Server 2012 i nowszych
Alberto Cláudio Mandlate
0
DECLARE  @m int
SET     @m = 2

SELECT 
       @m AS [Month],
       DATEDIFF(DAY,
                DATEADD(DAY, 0, DATEADD(m, +@m -1, 0)),
                DATEADD(DAY, 0, DATEADD(m,+ @m, 0))
               ) AS [Days in Month]
Danyil Vlasov
źródło
0
RETURN day(dateadd(month, 12 * @year + @month - 22800, -1)) 
select day(dateadd(month, 12 * year(date) + month(date) - 22800, -1)) 
Milan Hettner
źródło
-1

Na każdą randkę

select DateDiff(Day,@date,DateAdd(month,1,@date))
Sujith
źródło
-1
DECLARE @date nvarchar(20)
SET @date ='2012-02-09 00:00:00'
SELECT DATEDIFF(day,cast(replace(cast(YEAR(@date) as char)+'-'+cast(MONTH(@date) as char)+'-01',' ','')+' 00:00:00' as datetime),dateadd(month,1,cast(replace(cast(YEAR(@date) as char)+'-'+cast(MONTH(@date) as char)+'-01',' ','')+' 00:00:00' as datetime)))
ATUL KALASKAR
źródło
-1

proste zapytanie w SQLServer2012:

wybierz dzień (('20-05-1951 22:00:00'))

Testowałem dla wielu dat i zawsze zwracałem poprawny wynik

zied zelfani
źródło
2
SELECT DAY (CAST ('1951-05-20' AS DATE)) zwraca 20, czyli część dnia w dacie. Nie zwraca liczby dni w miesiącu maju.
Nawet Mien
-1

select first_day = dateadd (dd, -1 * datepart (dd, getdate ()) + 1, getdate ()), last_day = dateadd (dd, -1 * datepart (dd, dateadd (mm, 1, getdate ())) , dateadd (mm, 1, getdate ())), no_of_days = 1 + datediff (dd, dateadd (dd, -1 * datepart (dd, getdate ()) + 1, getdate ()), dateadd (dd, -1 * datepart (dd, dateadd (mm, 1, getdate ())), dateadd (mm, 1, getdate ())))

zamień dowolną datę na getdate, aby uzyskać liczbę miesięcy w tej konkretnej dacie

Macierze
źródło
-1
DECLARE @Month INT=2,
    @Year INT=1989
DECLARE @date DateTime=null
SET @date=CAST(CAST(@Year AS nvarchar) + '-' + CAST(@Month AS nvarchar) + '-' + '1' AS DATETIME);

DECLARE @noofDays TINYINT 
DECLARE @CountForDate TINYINT
SET @noofDays = DATEPART(MONTH,@date )
SET @CountForDate = 28 + (@noofDays + floor(@noofDays/8)) % 2 + 2 %    @noofDays + 2 * floor(1/@noofDays)   
SET @noofDays= @CountForDate + CASE WHEN @CountForDate = 28 AND DATEPART(YEAR,@date)%4 =0 THEN 1 ELSE 0 END
PRINT @noofDays
Diabelski
źródło
1
Cześć i witaj w SO! Chociaż kod może mówić sam za siebie, podanie pewnych szczegółów poprawiłoby jakość Twojej odpowiedzi!
mrun