Zapytanie porównujące daty w SQL

84

Mam tabelę z datami, które wydarzyły się w miesiącu listopadzie. Napisałem to zapytanie

select id,numbers_from,created_date,amount_numbers,SMS_text 
from Test_Table
where 
created_date <= '2013-04-12'

To zapytanie powinno zwrócić wszystko, co wydarzyło się w miesiącu 11 (listopad), ponieważ wydarzyło się to przed datą „2013-04-12” (w grudniu)

Ale to powrót tylko wolne terminy, które miały miejsce w dniach mniejsza niż 04 (2013- 04 -12)

Czy to możliwe, że porównuje tylko część dzienną? a nie cała randka?

Jak to naprawić?

Created_date jest typu date

Format daty to domyślnie rrrr-dd-MM

HelpASisterOut
źródło
1
Porównujesz daty do łańcuchów, a nie dat do dat
Panagiotis Kanavos
4
Może myśli 2013-04-12? jest 12 kwietnia? A może created_dateto string, a nie data?
jpw
Zapoznaj się z instrukcją Cast & Convert on T-SQL i użyj odpowiedniej konwersji dla swojej lokalizacji
Steve,
3
Nie musisz w ogóle przesyłać, po prostu użyj niezmiennego formatu „20130412”
Panagiotis Kanavos
1
Zamiast wysyłać ciąg z datą, spróbuj utworzyć zapytanie sparametryzowane i przekaż datę jako parametr z typem daty. BTW, jakiej wersji SQL Server używasz? Data została dodana w SQL Server 2008.
Panagiotis Kanavos

Odpowiedzi:

84

Zamiast „2013-04-12”, którego znaczenie zależy od lokalnej kultury, użyj „20130412”, który jest rozpoznawany jako niezmienny format kultury.

Jeśli chcesz porównać dane z 4 grudnia , wpisz „20131204”. Jeśli chcesz porównać z 12 kwietnia th , należy napisać „20130412”.

Artykuł Write International Transact-SQL Statements z dokumentacji SQL Server wyjaśnia, jak pisać instrukcje, które są niezmienne kulturowo:

Aplikacje korzystające z innych interfejsów API lub skryptów języka Transact-SQL, procedur składowanych i wyzwalaczy powinny używać nierozdzielonych ciągów liczbowych. Na przykład rrrrmmdd jako 19980924.

EDYTOWAĆ

Ponieważ używasz ADO, najlepszą opcją jest sparametryzowanie zapytania i przekazanie wartości daty jako parametru daty. W ten sposób całkowicie unikniesz problemu z formatem i uzyskasz korzyści z wydajności również sparametryzowanych zapytań.

AKTUALIZACJA

Aby użyć formatu ISO 8601 w literale, należy określić wszystkie elementy. Cytując z sekcji ISO 8601 dokumentacji datetime

Aby użyć formatu ISO 8601, musisz określić każdy element w formacie. Obejmuje to również T, dwukropki (:) i kropkę (.), Które są wyświetlane w formacie.

... ułamek drugiego składnika jest opcjonalny. Składnik czasu jest określany w formacie 24-godzinnym.

Panagiotis Kanavos
źródło
@andy niezupełnie, format ISO8601 zawiera element czasu. Albo jak docs powiedzieć , To use the ISO 8601 format, you must specify each element in the format. This also includes the T.
Panagiotis Kanavos
1
Przepraszam za niejasność, chodziło mi o to, że ISO8601 definiuje kolejność dokładnie tak, jak opisałeś: RRRR-MM-DD lub w skrócie RRRRMMDD. Jednak, jak podano w dokumentacji: „data / godzina nie jest zgodna z ANSI ani ISO 8601”. Samo ISO nie wymagałoby części czasowej.
andy
To, do czego się odnosisz, nie zmienia faktu, że nieYYYY-MM-DD jest rozpoznawany jako ISO 8601. Wymagane części czasowe . Nazwij to dziwnością T-SQL, jeśli chcesz, lub niepełną implementacją. Może się nawet zdarzyć, że zostało to przeniesione z Sybase
Panagiotis Kanavos
32

Spróbuj w ten sposób

select id,numbers_from,created_date,amount_numbers,SMS_text 
from Test_Table
where 
created_date <= '2013-12-04'
Nithesh Narayanan
źródło
6
Format specyficzny dla kultury. Czy to 12 kwietnia czy 4 grudnia? Format rozdzielany myślnikami NIE jest formatem międzynarodowym
Panagiotis Kanavos,
1
Więc co się dzieje, gdy musisz przechowywać dane od klientów międzynarodowych? A może data pochodzi z przeglądarki internetowej, która podąża za kulturą użytkownika ? Wytyczne istnieją z jakiegoś powodu i po prostu NIE używając niewłaściwego formatu, unikasz wszystkich błędów
Panagiotis Kanavos,
1
@Nithesh To powraca 12 kwietnia
HelpASisterOut
19
@PanagiotisKanavos Format rozdzielany myślnikami jest formatem międzynarodowym od czasu opublikowania ISO 8601 w 1988 roku. Inne formaty są odradzane i wyśmiewane . Nawet artykuł, który opublikowałeś, „Pisz międzynarodowe instrukcje języka Transact-SQL” ani razu nie określa „rrrrmmdd” jako jakiegokolwiek „międzynarodowego” standardu.
Jesse Webb
2
Dodanie pojedynczych cudzysłowów wokół daty rozwiązało ten problem. Używał formatu 2/19/2015. Zmieniono na „2/19/2015” i zaczęło działać. Dzięki za prosty pomysł.
Ethan Turk
10

W przypadku porównywania tylko z datą vale, a następnie przekształcenie go do tej pory (nie datetime ) będzie działać

select id,numbers_from,created_date,amount_numbers,SMS_text 
 from Test_Table
 where 
 created_date <= convert(date,'2013-04-12',102)

Ta konwersja jest również zastosowanie w użyciu GetDate () funkcji

Bimzee
źródło
4

Położysz <=i złapie podaną datę. Możesz go zastąpić <tylko.

Kuzgun
źródło
2

spróbuj z poniższym zapytaniem

select id,numbers_from,created_date,amount_numbers,SMS_text 
from Test_Table
where 
convert(datetime, convert(varchar(10), created_date, 102))  <= convert(datetime,'2013-04-12')
Naresh Pansuriya
źródło
0

Format daty to rrrr-mm-dd. Więc powyższe zapytanie szuka rekordów starszych niż 12 kwietnia 2013

Zaproponuj szybkie sprawdzenie, ustawiając ciąg daty na „2013-04-30”, jeśli nie ma błędu sql, format daty zostanie potwierdzony na rrrr-mm-dd.

Bowie
źródło
0

Spróbuj użyć znaku „#” przed i po dacie i upewnij się, jaki jest format daty w systemie. może "RRRRMMDD O RRRR-MM-DD O MM-DD-RRRR O USING '/ O \'"

Dawny:

 select id,numbers_from,created_date,amount_numbers,SMS_text 
 from Test_Table
 where 
 created_date <= #2013-04-12#
Ren Marín
źródło