2010-09-20 5 views
8

Ho una procedura memorizzata T-SQL in cui voglio cercare un valore particolare e facoltativamente limitare la ricerca a date particolari se vengono passate. Se i valori nulli sono passato per una di queste date, poi voglio ignorarle. Il modo in cui sto pensando di farlo impostando le date di input al minimo o al massimo se sono nulle. Preferirei non codificare i valori minimi e massimi. Quindi mi chiedo quale sia l'equivalente SQL di C# DateTime.MaxValue e DateTime.MinValue.Ricerca SQL per data tra valori o Min/Max se NULL

Sto pensando di utilizzare Coalesce in questo modo

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

c'è una costruito in funzione/costante/variabile/enum posso utilizzare per le variabili <MinDateTime> e <MaxDateTime>?

Qualche suggerimento?

risposta

11

Non esiste tale funzionalità in SQL Server. È possibile trovare facilmente min and max dates consentito in BOL (1753-01-01 - 9999-12-31). Oppure potresti facilmente codificare un'altra data facilmente (se davvero stai lavorando con i compleanni, probabilmente il 1800-01-01 - 2100-12-31 è sufficiente). Oppure si potrebbe (se è la query gamma avete dimostrato), avete la coalesce ricadere al compleanno stessa:

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

Ma si noti che questo non sarà necessariamente in scala bene per tabelle molto grandi.

cura dopo accettare, per rispondere alle osservazioni da OP

In generale, per SQL, se si sta bisogno di dati di "riferimento" di frequente, si aggiunge come un tavolo da soli. (Google per "tabella calendario" o "tabella numero sql"). Quindi, in questo caso, se si volesse, si potrebbe aggiungere un "costanti" (o forse tabella "limiti"):

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 

cui si potrebbe quindi fare riferimento nelle query (sia attraverso una selezione secondaria, o mediante giunzione a questo tavolo). Per esempio.

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

(la serratura, chiave primaria, e Check vincolo, lavorare insieme per assicurare che solo una singola riga sarà mai esistere in questa tabella)

+0

Molto interessante. Non avevo mai visto il tipo di pattern di Coalesce (@StartDate, Birthday) prima. Penso che la creazione di una variabile chiamata maxdate e mindate e l'impostazione dei suoi valori sulle date hardcoded potrebbe essere molto più leggibile. Ma sì, le informazioni principali che stavo cercando erano la mancanza delle enumerazioni/costanti in SQL – Chaitanya

+0

trucco Re COALESCE - +1 alla dichiarazione che non sarebbe scalabile per tabelle di grandi dimensioni, SQL Server non sembra essere in grado di utilizzare l'indice sulla colonna di compleanno. Le date min e max con hard coding funzionano bene con l'indice. –

3

Non ci sono funzioni incorporate per ottenere i valori di tempo di data minima o massima. È necessario codificare in modo rigido i valori o recuperare i valori dal database.

Se i parametri sono NULL, è sufficiente selezionare il minimo & date dal tavolo Employee.

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

non credo che questo è quello che voleva dire Chaitanya. –

+0

+1 Potrebbe non essere esattamente quello che chiedeva Chaitanya ma soddisfa abbastanza bene i requisiti. Non sono necessari hardcoding di min e max datetime necessari e la stessa query può essere utilizzata anche per casi null – InSane

4

Per SQL Server in particolare, secondo BOL, i limiti sono :

  • datetime: 1753/01/01 00:00:00 attraverso 9999-12-31 23: 59: 59,997
  • smalldatetime: 1900-01-01 00:00:00 attraverso 2079-06- 06 23: 59: 29.998
  • date: 0001-01-01 a 9999-12-31
  • datetime2: 0001-01-01 00:00:00 a 9999-12-31 23:59:59.9999999

Come si può vedere, dipende dal tipo di dati esatti.

Per quanto riguarda la domanda, lo farei in questo modo:

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

+1 per riferimenti. Per quanto riguarda la query, è necessario testarla, "TRA ... COALESCE" potrebbe essere più comprensibile per il pianificatore di query. – Unreason