2010-09-20 6 views
8

Mam procedurę składowaną T-SQL, w której chcę wyszukać określoną wartość i opcjonalnie ograniczyć wyszukiwanie do określonych dat, jeśli są one przekazywane. Jeśli wartości null są przekazane w którejkolwiek z tych dat, to chcę je zignorować. Sposób, w jaki myślę o tym, ustawiając daty wejściowe na minimum lub maksimum, jeśli są one zerowe. Wolałbym jednak, aby nie kodować wartości minimalnej i maksymalnej. Więc zastanawiam się, co to jest odpowiednik SQL C# DateTime.MaxValue i DateTime.MinValue.Wyszukiwanie SQL dla daty między wartościami lub Min/Max jeśli NULL

mam na myśli używając zlewają jak tak

SELECT EmployeeName FROM Employee 
WHERE EmployeeID = @EmployeeId AND 
Birthday BETWEEN Coalesce(@StartDate, <MinDateTime>) AND 
       Coalesce(@EndDate, <MaxDateTime>) 

Czy jest wbudowany w funkcji/stałej/zmiennej/enum mogę wykorzystać dla <MinDateTime> i <MaxDateTime> zmiennych?

Wszelkie sugestie?

Odpowiedz

11

Nie ma takiej funkcji w SQL Server. Możesz łatwo znaleźć min and max dates dozwoloną w BOL (1753-01-01 - 9999-12-31). Albo możesz łatwo zakodować inną datę (jeśli naprawdę pracujesz z urodzinami, prawdopodobnie wystarczą 1800-01-01 - 2100-12-31). Lub można (jeśli jest kwerenda zakres masz pokazane), mają COALESCE spaść z powrotem na urodzinach samego:

SELECT EmployeeName FROM Employee 
WHERE EmployeeID = @EmployeeId AND 
Birthday BETWEEN Coalesce(@StartDate, Birthday) AND 
       Coalesce(@EndDate, Birthday) 

Należy jednak pamiętać, że to niekoniecznie dobrze skalować dla bardzo dużych tabel.

Zmieniano po przyjąć, aby odpowiedzieć na komentarz z OP

Generalnie dla SQL, jeśli potrzebują „referencyjne” dane często, należy dodać go jako tabeli samodzielnie. (Google dla "tabeli kalendarza" lub "tabeli numerycznej sql"). Więc w tym przypadku, jeśli chcesz, możesz dodać „stałe” (albo „granic” tabeli):

create table Constants (
    Lock char(1) not null, 
    datetimeMin datetime not null, 
    datetimeMax datetime not null, 
    intMin int not null, 
    intMax int not null, 
    /* Other Min/Max columns, as required */ 
    constraint PK_Constants PRIMARY KEY (Lock), 
    constraint CK_Constants_Locked CHECK (Lock='X') 
) 
insert into Constants (Lock,datetimeMin,datetimeMax,intMin,intMax) 
select 'X','17530101','99991231',-2147483648,2147483647 

które można następnie odwoływać w zapytaniach (poprzez podselekcji lub przez krzyż łączące do tej tabeli). Na przykład.

SELECT EmployeeName 
FROM Employee, Constants 
WHERE EmployeeID = @EmployeeId AND 
Birthday BETWEEN Coalesce(@StartDate, Constants.datetimeMin) AND 
       Coalesce(@EndDate, Constants.datetimeMax) 

(Blokada, klucz podstawowy i sprawdź ograniczenia, współpracować, aby upewnić się, że tylko jeden wiersz będzie kiedykolwiek istnieć w tej tabeli)

+0

Bardzo interesujące. Nigdy wcześniej nie widziałem schematu Coalesce (@StartDate, Urodziny). Myślę, że utworzenie zmiennej o nazwie maxdate i mindate oraz ustawienie jej wartości na stałe daty może być dużo bardziej czytelne. Ale tak, główną informacją, której szukałem, był brak wyliczeń/stałych w sztuczce SQL – Chaitanya

+0

Re COALESCE - +1 do stwierdzenia, że ​​nie byłby skalowalny dla dużych tabel, SQL Server nie wydaje się być w stanie używać indeksu w kolumnie Urodziny. Twarde kodowanie min i maks. Terminów działa dobrze z indeksem. –

3

Nie ma wbudowanych funkcji pozwalających uzyskać wartości minimalnej lub maksymalnej wartości daty. Musisz mocno zakodować wartości lub pobrać wartości z bazy danych. Jeśli masz parametry NULL, możesz po prostu wybrać min.

IF (@StartDate IS Null) 
BEGIN 
SELECT @StartDate = MIN(Birthday) FROM Employee 
END 


IF (@EndDate IS Null) 
BEGIN 
SELECT @EndDate = MAX(Birthday) FROM Employee 
END 

SELECT EmployeeName FROM Employee 
WHERE EmployeeID = @EmployeeId AND 
Birthday BETWEEN @StartDate AND @EndDate 
+1

I nie sądzę, że to jest to, co Caitanya myśli. –

+0

+1 To może nie być dokładnie to, o co prosił Chaitanya, ale wystarczająco spełnia wymagania. Żadne kodowanie minimalnej i maksymalnej daty i godziny nie jest potrzebne, a to samo zapytanie może być używane również w przypadku zerowych wartości. – InSane

4

Dla SQL Server konkretnie, zgodnie z BOL, limity są :

  • datetime: 01.01.1753 0:00:00 przez 9999-12-31 23: 59: 59,997
  • smalldatetime: 01.01.1900 0:00:00 poprzez 2079-06- 06 23: 59: 29,998
  • date: 0001-01-01 do 9999-12-31
  • datetime2: 0001-01-01 00:00:00 do 9999-12-31 23:59:59.9999999

Jak widać, zależy to od dokładnego typu danych.

chodzi o zapytaniu, zrobiłbym to tak:

SELECT EmployeeName 
FROM Employee 
WHERE EmployeeID = @EmployeeId 
AND (@StartDate IS NULL 
    OR Birthday >= @StartDate) 
AND (@EndDate IS NULL 
    OR Birthday <= @EndDate) 
+0

+1 dla referencji. Jeśli chodzi o zapytanie - musi zostać przetestowane, "MIĘDZY ... COALESCE" może być bardziej zrozumiałe dla planera zapytań. – Unreason

Powiązane problemy