Làm cách nào tôi có thể chọn ngày đầu tiên của tháng trong SQL?


308

Tôi chỉ cần chọn ngày đầu tiên của tháng của một biến thời gian đã cho.

Tôi biết việc sử dụng loại mã này khá dễ dàng:

select CAST(CAST(YEAR(@mydate) AS VARCHAR(4)) 
+ '/' + CAST(MONTH(@mydate) AS VARCHAR(2)) + '/01' AS DATETIME)

Nhưng điều này không phải là rất thanh lịch, và có lẽ cũng không nhanh lắm.

Có cách nào tốt hơn để làm điều này? Tôi đang sử dụng SQL Server 2008.

Câu trả lời:


604
SELECT DATEADD(month, DATEDIFF(month, 0, @mydate), 0) AS StartOfMonth


63
Cần lưu ý rằng lỗi được đề cập bởi Martin Smith có thể "chỉ" ảnh hưởng đến hiệu suất, chứ không phải tính chính xác.
Olson.dev


34
Trong trường hợp bất cứ ai đang tự hỏi SELECT EOMONTH(@mydate) AS EndOfMonthsẽ cung cấp cho bạn ngày cuối cùng của tháng.
hallizh

3
Làm cách nào để xác định xem lỗi ước tính cardinality có ảnh hưởng đến tôi không? Nó được đánh dấu là cố định vào năm 2010. Điều đó có nghĩa là chỉ SQL Server 2012 và mới hơn là an toàn, hoặc có thể máy chủ 2008 có thể đã được vá?
Jon

134

Ngoài tất cả các câu trả lời trên, một cách dựa trên một chức năng được giới thiệu trong sql 2012

SELECT DATEFROMPARTS(YEAR(@mydate),MONTH(@mydate),1)


14

Việc truyền chuỗi (tức là "5/1/2009") thành datetime chắc chắn dễ đọc hơn nhưng chúng tôi đã tìm thấy mã một thời gian trước đó sẽ trả về đầu tiên của tháng ...

DECLARE @Date DATETIME
//...
SELECT DATEADD(mm, DATEDIFF(mm,0,@Date), 0)

10

Truy vấn đơn giản:

SELECT DATEADD(m, DATEDIFF(m, 0, GETDATE()), 0) 
-- Instead of GetDate you can put any date.

6

Nó có lẽ là khá nhanh. Tại sao không tạo ra nó như là một hàm sql.

CREATE FUNCTION [dbo].[GetFirstDayOfMonth] ( @InputDate    DATETIME )
RETURNS DATETIME
BEGIN

    RETURN CAST(CAST(YEAR(@InputDate) AS VARCHAR(4)) + '/' + 
                CAST(MONTH(@InputDate) AS VARCHAR(2)) + '/01' AS DATETIME)

END
GO

4

Điều này cũng hoạt động:

    SELECT DATEADD(DAY,(DATEPART(DAY,@mydate)-1)*(-1),@mydate) AS FirstOfMonth

3

Vui lòng sử dụng cái này

  1. Dành cho máy chủ 2012

    DATEFROMPARTS(year('2015-06-30'),month('2015-06-30'),1)
  2. Trước máy chủ 2012

    select  cast(cast(year('2015-06-30') as varchar(4))+'-'+ cast(month('2015-06-30') as varchar(2))+'-01' as smalldatetime)

3

Ngày đầu tiên và ngày cuối cùng của tháng hiện tại:

select dateadd(mm, -1,dateadd(dd, +1, eomonth(getdate()))) as FirstDay, 
eomonth(getdate()) as LastDay

2
SELECT @myDate - DAY(@myDate) + 1

Giải pháp thực sự đơn giản và thanh lịch nhưng hãy nhớ rằng điều này cũng trả về phần thời gian của ngày nếu được chỉ định trong biến.
kuklei

Tôi không thể làm việc này. Ngoài khung đóng thêm, tôi gặp lỗi này : Operand type clash: date is incompatible with int. Tôi đoán đó là vì bạn đang cố gắng sử dụng -toán tử vào một ngày?
Sam

Tôi không biết nó tốt như thế nào về hiệu suất, nhưng nó chắc chắn làm được việc.
salcoin

@Sam, bạn đã có một cuộc đụng độ vì số học đơn giản (+, -) hoạt động trên các mốc thời gian, không phải vào ngày.
darlove

2
----Last Day of Previous Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0))
LastDay_PreviousMonth
----Last Day of Current Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0))
LastDay_CurrentMonth
----Last Day of Next Month
SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+2,0))
LastDay_NextMonth

Nhưng OP đang tìm kiếm ngày đầu tiên của tháng. Đối với ngày cuối cùng, bạn chỉ có thể sử dụng EOMONTH () - đã theo cách này kể từ năm 2012.
deutschZuid


1

Các nhân viên Google trong tương lai, trên MySQL, hãy thử điều này:

select date_sub(ref_date, interval day(ref_date)-1 day) as day1;

3
Đây là một sql-servercâu hỏi, date_subintervalmysql.
OGHaza

Tốt, điểm, tôi chỉnh sửa các phản ứng. Tôi nghĩ rằng nó vẫn còn liên quan đến chủ đề.
Ariel T

1

Tôi đã sử dụng GETDATE () làm ngày để làm việc, bạn có thể thay thế nó bằng ngày mà bạn cần.
Đây là cách thức hoạt động: Đầu tiên chúng tôi định dạng ngày theo định dạng YYYYMMDD ... để cắt chỉ 6 ký tự ngoài cùng bên trái để chỉ giữ phần YYYYMM, sau đó thêm '01' làm tháng - và voila! bạn có ngày đầu tiên của tháng hiện tại

SELECT CAST(CONVERT(VARCHAR(6),GETDATE(),112) +'01' AS DATETIME) AS StartOfMonth

BTW, hiệu suất là tuyệt vời về điều này!


1

Nếu bạn đang xem xét điều này ngày hôm nay và sử dụng máy chủ SQL 2012 hoặc mới hơn, bạn có chức năng EOMONTH giúp mọi việc dễ dàng hơn:

SELECT DATEADD(day, 1, EOMONTH(DATEADD(month, -1, GETDATE()))) as firstdateofmonth

Bạn có thể thay đổi GETDATE () với bất kỳ biến ngày nào bạn muốn.


1

Ở đây chúng ta có thể sử dụng truy vấn dưới đây cho đến ngày đầu tiên của tháng và ngày cuối cùng của tháng.

SELECT DATEADD(DAY,1,EOMONTH(Getdate(),-1)) as 'FD',Cast(Getdate()-1 as Date)
as 'LD'

1

Nếu sử dụng SQL Server 2012 trở lên;

SELECT DATEADD(MONTH, -1, DATEADD(DAY, 1, EOMONTH(GETDATE())))

1
DECLARE @startofmonth date
SET @startofmonth = DATEADD(dd,1,EOMONTH(Getdate(),-2))

-2 sẽ giúp bạn có được ngày đầu tiên của tháng trước. tức là, getdate () là 10/15/18. Kết quả của bạn sẽ là 9/1/18. Thay đổi thành -1 và kết quả của bạn sẽ là 10/1/18. 0 sẽ là bắt đầu của tháng tới, 11/1/2018 .. vv.

hoặc là

DECLARE @startofmonth date
SET @startofmonth = DATEADD(dd,1,EOMONTH(@mydate,-1))

1

Hãy thử thực hiện truy vấn sau:

SELECT DATE_ADD(DATE_ADD(LAST_DAY(CURRENT_DATE-INTERVAL 1 DAY),INTERVAL 1 DAY),INTERVAL -1 MONTH)


0

chọn CHUYỂN ĐỔI (ngày, DATEADD (dd, - (DATEPART (dd, getdate ()) - 1), getdate ()), 120)

Chức năng này sẽ cung cấp cho bạn một phần của ngày bắt đầu của tháng


0
SELECT DATEADD (DAY, -1 * (DAY(GETDATE()) - 1), GETDATE())

.................................................. ...................

Nếu bạn không muốn thời gian, sau đó chuyển đổi nó thành DATE hoặc nếu muốn thực hiện thành thời gian thành 0:00:00, Chuyển đổi thành DATE và sau đó quay lại DATETIME.

SELECT CONVERT (DATETIME,  
CONVERT (DATE, DATEADD (DAY, -1 * (DAY(GETDATE()) - 1),
GETDATE())))

Thay đổi GETDATE () thành ngày bạn muốn


0

Tôi cá nhân khuyến nghị rằng sql bên dưới bởi vì khi tôi thử sử dụng hàm ngày trong mệnh đề điều kiện, nó làm chậm tốc độ truy vấn của tôi rất nhiều.

dù sao đi nữa, hãy thử nó

select CONCAT(DATEPART(YYYY,@mydate),'-',DATEPART(MM,@mydate),'-01')

0

Không phải để cạnh tranh với bất kỳ bộ óc vĩ đại nào ở đây, nhưng một gợi ý đơn giản hơi khác biệt mà câu trả lời được chấp nhận ở trên.

select dateadd(day, -(datepart(day,@date)+1,@date)

0

Tôi thích sử dụng FORMAT, bạn thậm chí có thể chỉ định thời gian

SELECT FORMAT(@myDate,'yyyy-MM-01 06:00') first_of_a_month

0

Trong máy chủ Sql 2012,

 select getdate()-DATEPART(day, getdate())+1

 select DATEADD(Month,1,getdate())-DATEPART(day, getdate())


0

Đối với bất cứ ai vẫn đang tìm kiếm một câu trả lời, điều này hoạt động như một sự quyến rũ và không có bất kỳ dữ liệu nào. Dấu thời gian là tùy chọn, trong trường hợp cần chỉ định, nhưng cũng hoạt động mà không cần.

SELECT left(convert(varchar, getdate(),23),7)+'-01 00:00:00'

0

Nhận ngày đầu tiên và ngày cuối cùng trong ngày chúng tôi chuyển qua làm tham số trong SQL

     @date DATETIME
    SELECT @date = GETDATE()
    SELECT CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(@date)-1),@date),105) AS value,
    'First Day of Current Month' AS name
    UNION
    SELECT CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,1,@date))),
    DATEADD(mm,1,@date)),105),
    'Last Day of Current Month'
    GO


      **OutPut**

12/01/2019  First Day of Current Month
12/31/2019  Last Day of Current Month

-3

Đây là cách bạn làm điều đó trong MySQL:

  select DATE_FORMAT(NOW(), '%Y-%m-1')

4
Vui lòng xác định rằng đây không phải là câu trả lời của máy chủ sql mà chỉ hoạt động trên MySQL.
kuklei

Đối với SQL Server, bạn có thể sử dụngSELECT FORMAT(GETDATE(), 'yyyy-MM-01')
NASSER

Đừng khuyến khích mọi người định dạng ngày thành chuỗi chỉ để làm điều gì đó có thể và nên được thực hiện bằng số. Nó giống như nói rằng "bạn có thể làm tròn một số xuống 100 gần nhất bằng cách định dạng nó thành một chuỗi, đặt nền tảng trừ hai chữ số cuối cùng và ghép vào một '00'"
Caius Jard
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.