SQL Server datetime LIKE chọn?


92

trong MySQL

select * from record where register_date like '2009-10-10%'

Cú pháp trong SQL Server là gì?


Bạn thực sự muốn kiểm tra điều gì? Đó là một ngày giờ nhất định có một phần ngày nhất định? Hay cái gì khác?
Chris J

1
Để có một cuộc thảo luận lành mạnh về vấn đề này (bao gồm lý do tại sao việc xử lý DATETIMEcác giá trị như chuỗi là không tốt và tại sao nó có thể không tốt khi sử dụng BETWEENhoặc >= AND <=), hãy xem blog này của Aaron Bertrand .
Aaron Bertrand

Câu hỏi của bạn có ít nhất 5phiếu bầu cho thẻ toán tử thích . Tôi có thể vui lòng yêu cầu bạn đề xuất sql-like như một từ đồng nghĩa không?
Kermit

Câu trả lời:


138

Bạn có thể sử dụng hàm DATEPART ()

SELECT * FROM record 
WHERE  (DATEPART(yy, register_date) = 2009
AND    DATEPART(mm, register_date) = 10
AND    DATEPART(dd, register_date) = 10)

Tôi thấy cách này dễ đọc, vì nó bỏ qua thành phần thời gian và bạn không cần phải sử dụng ngày của ngày hôm sau để hạn chế lựa chọn của mình. Bạn có thể đi đến mức độ chi tiết lớn hơn hoặc thấp hơn bằng cách thêm các mệnh đề bổ sung, sử dụng mã DatePart thích hợp, ví dụ:

AND    DATEPART(hh, register_date) = 12)

để có được các bản ghi được thực hiện từ 12 đến 1.

Tham khảo tài liệu MSDN DATEPART để biết danh sách đầy đủ các đối số hợp lệ.


Nếu có một chỉ mục trên register_date, điều này sẽ hoàn toàn bỏ qua chỉ mục và hiệu suất sẽ bị ảnh hưởng. Có lẽ là khá tệ.
Chris J

Được, nhưng nó không tránh được vấn đề sử dụng chuỗi tương đương ngày sau ngày được đề cập, đang được đề xuất trong một số câu trả lời ở đây. Thật khó hiểu khi ngày được đề cập là cuối tháng hoặc năm.
Ralph Lavelle,

60

Không có hỗ trợ trực tiếp cho toán tử LIKE đối với các biến DATETIME, nhưng bạn luôn có thể truyền DATETIME thành VARCHAR:

SELECT (list of fields) FROM YourTable
WHERE CONVERT(VARCHAR(25), register_date, 126) LIKE '2009-10-10%'

Kiểm tra tài liệu MSDN để biết danh sách đầy đủ các "kiểu" có sẵn trong chức năng CHUYỂN ĐỔI.

Marc


1
đồng ý - nhưng OP yêu cầu một cách để xử lý datetime với NHƯ .... Nhưng tôi đồng ý - datetimes tốt nhất nên được xử lý với các phạm vi như> = và <= hoặc GIỮA - nhiều hơn cách tiếp cận
marc_s

Cảm ơn mọi người. Xin lỗi, tôi chỉ là một người mới sử dụng SQL.
Paisal

1
Hãy lưu ý, MSSQL 2012 (tôi cũng đoán là các phiên bản cũ hơn) sẽ chuyển đổi datetime thành varchar là '2014-01-06T16: 18: 00.045', vì vậy hãy ghi nhớ điều này nếu bạn cũng cố gắng khớp với giờ / phút.
balint

Các chỉ hành tôi đã có với sql trên chọn là thế này: WHERE CONVERT(VARCHAR(25), register_date, 25) LIKE '2009-10-10%'
Gabriel Marius Popescu

10

Nếu bạn làm điều đó, bạn đang buộc nó thực hiện chuyển đổi chuỗi. Sẽ tốt hơn nếu bạn xây dựng phạm vi ngày bắt đầu / kết thúc và sử dụng:

declare @start datetime, @end datetime
select @start = '2009-10-10', @end = '2009-11-10'
select * from record where register_date >= @start
           and register_date < @end

Điều này sẽ cho phép nó sử dụng chỉ mục (nếu có một trên register_date), thay vì quét bảng.


Cảm ơn bạn. Xin lỗi, tôi chỉ là một người mới sử dụng SQL.
Paisal

8

Bạn có thể sử dụng CONVERT để lấy ngày ở dạng văn bản. Nếu bạn chuyển đổi nó thành varchar (10), bạn có thể sử dụng = thay vì like:

select *
from record
where CONVERT(VARCHAR(10),register_date,120) = '2009-10-10'

Hoặc bạn có thể sử dụng ngày cận trên và cận dưới, với lợi thế bổ sung là nó có thể sử dụng chỉ mục:

select *
from record
where '2009-10-10' <= register_date
and register_date < '2009-10-11'

Tôi nghĩ rằng đó là lỗi đánh máy trong mệnh đề where, nó phải là "nơi '2009/10/10'> = register_date"
Vishwanath Dalvi

@mr_eclair: đừng nghĩ vậy, điều đó sẽ bao gồm mọi ngày trước ngày 11 tháng 10
Andomar

7

Thật không may, không thể so sánh datetime với varchar bằng cách sử dụng 'LIKE' Nhưng kết quả mong muốn có thể theo cách khác.

    select * from record where datediff(dd,[record].[register_date],'2009-10-10')=0

3

Bạn cũng có thể sử dụng chuyển đổi để làm cho ngày có thể tìm kiếm được bằng cách sử dụng LIKE. Ví dụ,

select convert(VARCHAR(40),create_date,121) , * from sys.objects where     convert(VARCHAR(40),create_date,121) LIKE '%17:34%'

2

Các LIKEnhà điều hành không làm việc với các bộ phận ngày như tháng hoặc ngày nhưng DATEPARTnhà điều hành thực hiện.

Lệnh để tìm ra tất cả các tài khoản có Ngày mở là ngày 1:

SELECT * 
  FROM Account 
 WHERE DATEPART(DAY, CAST(OpenDt AS DATE)) = 1`

* ĐÚC OpenDtvì giá trị của nó là ở trong DATETIMEvà không chỉ DATE.


1

Có một phạm vi rất mỏng của toán tử LIKE cho các ngày trong SQL Server. Nó chỉ hoạt động bằng cách sử dụng định dạng ngày của Mỹ. Ví dụ bạn có thể thử:

... WHERE register_date LIKE 'oct 10 2009%'

Tôi đã thử nghiệm điều này trong SQL Server 2005 và nó hoạt động, nhưng bạn sẽ thực sự cần thử các kết hợp khác nhau. Những điều kỳ lạ tôi nhận thấy là:

  • Bạn dường như chỉ nhận được tất cả hoặc không nhận được gì cho các trường phụ khác nhau trong ngày, ví dụ: nếu bạn tìm kiếm 'apr 2%', bạn chỉ nhận được bất kỳ thứ gì trong ngày 20 - nó bỏ qua ngày thứ 2.

  • Ví dụ: sử dụng một dấu gạch dưới '_' để đại diện cho một ký tự (ký tự đại diện) hoàn toàn không hoạt động, WHERE mydate LIKE 'oct _ 2010%'sẽ không trả về tất cả các ngày trước đó 10 - trên thực tế, nó không trả về gì cả!

  • Định dạng cứng nhắc của Mỹ: ' mmm dd yyyy hh:mm'

Tôi cảm thấy rất khó để hoàn thành một quy trình cho những giây LIKE, vì vậy nếu ai muốn làm điều này xa hơn một chút, hãy là khách của tôi!

Hi vọng điêu nay co ich.


1

Tôi hơi muộn với chủ đề này nhưng trên thực tế có hỗ trợ trực tiếp cho toán tử tương tự trong máy chủ MS SQL.

Như được ghi lại trong LIKE trợ giúp nếu kiểu dữ liệu không phải là một chuỗi, nó sẽ cố gắng chuyển đổi nó thành một chuỗi. Và như được ghi lại trong tài liệu cast \ convert:

chuyển đổi datetime mặc định thành chuỗi là loại 0 (, 100) là mon dd yyyy hh: miAM (hoặc PM).

Nếu bạn có một ngày như thế này trong DB:

2015-06-01 11:52:59.057

và bạn thực hiện các truy vấn như thế này:

select * from wws_invoice where invdate like 'Jun%'
select * from wws_invoice where invdate like 'Jun 1%'
select * from wws_invoice where invdate like 'Jun 1 %'
select * from wws_invoice where invdate like 'Jun 1 2015:%'
select * from wws_invoice where invdate like 'Jun ? 2015%'
...
select * from wws_invoice where invdate like 'Jun 1 2015 11:52AM'

bạn nhận được hàng đó.

Tuy nhiên, định dạng ngày này gợi ý rằng đó là DateTime2 , sau đó tài liệu cho biết:

21 hoặc 121 - ODBC chuẩn (với mili giây) mặc định cho thời gian, ngày tháng, datetime2 và datetimeoffset. - yyyy-mm-dd hh: mi: ss.mmm (24h)

Điều đó làm cho nó dễ dàng hơn và bạn có thể sử dụng:

select * from wws_invoice where invdate like '2015-06-01%'

và lấy bản ghi hóa đơn. Đây là mã demo:

DECLARE @myDates TABLE (myDate DATETIME2);
INSERT INTO @myDates (myDate)
VALUES
('2015-06-01 11:52:59.057'),
('2015-06-01 11:52:59.054'),
('2015-06-01 13:52:59.057'),
('2015-06-01 14:52:59.057');

SELECT * FROM @myDates WHERE myDate LIKE '2015-06-01%';
SELECT * FROM @myDates WHERE myDate LIKE '2015-06-01 11%';
SELECT * FROM @myDates WHERE myDate LIKE '2015-06-01 11:52:59%';
SELECT * FROM @myDates WHERE myDate LIKE '2015-06-01 11:52:59.054%';

Thực hiện tìm kiếm ngày giờ trong máy chủ SQL mà không có bất kỳ chuyển đổi nào thành chuỗi luôn là vấn đề. Lấy từng phần ngày là một việc làm quá mức cần thiết (không chắc sẽ sử dụng chỉ mục). Có lẽ một cách tốt hơn khi bạn không sử dụng chuyển đổi chuỗi là sử dụng kiểm tra phạm vi. I E:

select * from record 
where register_date >= '20091010' and register_date < '20091011';

1

Thử cái này

SELECT top 10 * from record WHERE  IsActive = 1 and CONVERT(VARCHAR, register_date, 120) LIKE '2020-01%'

0

Tôi đã giải quyết vấn đề của mình theo cách đó. Cảm ơn bạn đã góp ý để cải tiến. Ví dụ trong C #.

string dd, mm, aa, trc, data;
dd = nData.Text.Substring(0, 2);
mm = nData.Text.Substring(3, 2);
aa = nData.Text.Substring(6, 4);
trc = "-";
data = aa + trc + mm + trc + dd;

"Select * From bdPedidos Where Data Like '%" + data + "%'";
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.