SQL Server datetime LIKE select?

92

w MySQL

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

Jaka jest składnia w SQL Server?

Paisal
źródło
Co tak naprawdę chcesz sprawdzić? Czy dana data i godzina ma określoną część dotyczącą daty? Albo coś innego?
Chris J
1
Aby uzyskać zdrową dyskusję na ten temat (w tym, dlaczego źle jest traktować DATETIMEwartości jak ciągi i dlaczego może to być złe w użyciu BETWEENlub >= AND <=), zobacz ten blog Aarona Bertranda .
Aaron Bertrand
Twoje pytanie ma przynajmniej 5głosów dla tagu like-operator . Mógłbym uprzejmą prośbą, które sugerują, SQL-like jako synonim ?
Kermit

Odpowiedzi:

138

Możesz użyć funkcji DATEPART ()

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

Uważam, że ten sposób jest łatwy do odczytania, ponieważ ignoruje składnik czasu i nie musisz używać daty następnego dnia, aby ograniczyć wybór. Możesz przejść do większej lub mniejszej szczegółowości, dodając dodatkowe klauzule, używając odpowiedniego kodu DatePart, np

AND    DATEPART(hh, register_date) = 12)

aby uzyskać zapisy wykonane między 12 a 1.

Skonsultować się z docs MSDN datepart po pełną listę ważnych argumentów.

Ralph Lavelle
źródło
Jeśli istnieje indeks w register_date, spowoduje to całkowite zignorowanie indeksu i pogorszy się wydajność. Prawdopodobnie bardzo źle.
Chris J
Ok, ale pozwala to uniknąć problemu z używaniem odpowiednika ciągu dnia następującego po dacie, o której mowa, co jest sugerowane w kilku odpowiedziach tutaj. Podstępne, gdy dana data to koniec miesiąca lub roku.
Ralph Lavelle
60

Nie ma bezpośredniego wsparcia dla operatora LIKE względem zmiennych DATETIME, ale zawsze możesz rzutować DATETIME na VARCHAR:

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

Sprawdź dokumentację MSDN, aby uzyskać pełną listę dostępnych „stylów” w funkcji KONWERTUJ.

Marc

marc_s
źródło
1
zgodził się - ale OP poprosił o sposób obsługi
daty i godziny za
Dziękuje wszystkim. Przepraszam, jestem tylko nowicjuszem w SQL.
Paisal
1
Należy pamiętać, że MSSQL 2012 (myślę, że starsze wersje również) przekonwertuje datetime na varchar jako '2014-01-06T16: 18: 00.045', więc miej to na uwadze, jeśli spróbujesz również dopasować godzinę / minutę.
balint
Jedyny problem, jaki miałem z powyższym wyborem sql, jest następujący: WHERE CONVERT(VARCHAR(25), register_date, 25) LIKE '2009-10-10%'
Gabriel Marius Popescu
10

Jeśli to zrobisz, zmusisz go do konwersji ciągów. Lepiej byłoby utworzyć zakres dat rozpoczęcia / zakończenia i użyć:

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

Umożliwi to wykorzystanie indeksu (jeśli jest włączony register_date) zamiast skanowania tabeli.

Marc Gravell
źródło
Dziękuję Ci. Przepraszam, że jestem nowicjuszem w SQL.
Paisal
8

Możesz użyć CONVERT, aby uzyskać datę w formie tekstowej. Jeśli przekonwertujesz go na varchar (10), możesz użyć = zamiast:

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

Lub możesz użyć daty górnej i dolnej granicy, z dodatkową zaletą, że może skorzystać z indeksu:

select *
from record
where '2009-10-10' <= register_date
and register_date < '2009-10-11'
Andomar
źródło
Myślę, że w klauzuli gdzie jest literówka, powinno to być „gdzie '2009-10-10'> = register_date”
Vishwanath Dalvi
@mr_eclair: nie myśl tak, to będzie obejmować każdą datę przed 11 października
Andomar
8

Niestety, nie jest możliwe porównanie daty i czasu z varchar przy użyciu „LIKE”, ale pożądane wyjście jest możliwe w inny sposób.

    select * from record where datediff(dd,[record].[register_date],'2009-10-10')=0
Dani Mathew
źródło
3

Możesz także użyć opcji Convert, aby umożliwić wyszukiwanie daty za pomocą funkcji LIKE. Na przykład,

select convert(VARCHAR(40),create_date,121) , * from sys.objects where     convert(VARCHAR(40),create_date,121) LIKE '%17:34%'
Steve M.
źródło
2

LIKEOperator nie działa z datą części jak miesiąc lub dacie aleDATEPART operator robi.

Polecenie, aby znaleźć wszystkie rachunki, których data otwarcia przypadała na 1:

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

* ODLEWANIE, OpenDtponieważ jest to wartość, DATETIMEa nie tylko DATE.

Mohit Sarin
źródło
2

Spróbuj tego

SELECT top 10 * from record WHERE  IsActive = 1 and CONVERT(VARCHAR, register_date, 120) LIKE '2020-01%'
Skała
źródło
1

W SQL Server występuje bardzo słabe pokrycie operatora LIKE dla dat. Działa tylko w amerykańskim formacie daty. Jako przykład możesz spróbować:

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

Przetestowałem to w SQL Server 2005 i działa, ale naprawdę musisz wypróbować różne kombinacje. Dziwne rzeczy, które zauważyłem, to:

  • Wydaje się, że otrzymujesz tylko wszystko lub nic dla różnych pól podrzędnych w danym terminie, na przykład, jeśli wyszukujesz „apr 2%”, otrzymujesz wszystko tylko w 20. - pomija drugie.

  • Używając jednego podkreślenia „_” reprezentuje pojedynczy znak (wieloznaczny) nie całkowicie pracy, na przykład, WHERE mydate LIKE 'oct _ 2010%'będzie nie zwróci wszystkie daty zanim się 10 - to nic nie zwraca w ogóle, w rzeczywistości!

  • Format jest sztywny amerykański: ' mmm dd yyyy hh:mm'

Trudno mi było ułożyć proces na LIKE sekundy, więc jeśli ktoś chce pójść dalej, bądź moim gościem!

Mam nadzieję że to pomoże.

Paweł
źródło
1

Trochę się spóźniłem na ten wątek, ale faktycznie istnieje bezpośrednie wsparcie dla operatora like w serwerze MS SQL.

Jak udokumentowano w pomocy LIKE, jeśli typ danych nie jest łańcuchem, następuje próba przekształcenia go w łańcuch. Jak udokumentowano w dokumentacji cast \ convert:

Domyślna konwersja daty i godziny na łańcuch to typ 0 (, 100), czyli poniedziałek dd rrrr hh: miAM (lub PM).

Jeśli masz taką datę w DB:

2015-06-01 11:52:59.057

i robisz takie zapytania:

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'

dostajesz ten wiersz.

Jednak ten format daty sugeruje, że jest to DateTime2 , a następnie dokumentacja mówi:

21 lub 121 - kanoniczne ODBC (z milisekundami) domyślne dla godziny, daty, daty i godziny 2 oraz przesunięcia daty i godziny. - rrrr-mm-dd hh: mi: ss.mmm (24h)

To ułatwia i możesz użyć:

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

i uzyskaj rekord faktury. Oto kod 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%';

Wykonywanie wyszukiwań typu data-godzina na serwerze SQL bez konwersji na ciąg zawsze było problematyczne. Uzyskanie każdej części daty to przesada (która prawdopodobnie nie użyłaby indeksu). Prawdopodobnie lepszym sposobem, gdy nie używasz konwersji ciągów, byłoby użycie kontroli zakresu. to znaczy:

select * from record 
where register_date >= '20091010' and register_date < '20091011';
Cetin Basoz
źródło
0

W ten sposób rozwiązałem swój problem. Dziękuję za sugestie dotyczące ulepszeń. Przykład w 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 + "%'";
Eronildo Barbosa
źródło