2010-09-20 9 views
8

Tengo un procedimiento almacenado T-SQL en el que quiero buscar un valor particular y opcionalmente limitar la búsqueda a fechas particulares si se pasan. Si los valores nulos son pasado para cualquiera de estas fechas, entonces quiero ignorarlas. La forma en que pienso hacer esto es establecer las fechas de entrada al mínimo o máximo si son nulas. Sin embargo, preferiría no codificar los valores mínimos y máximos. Así que me pregunto qué son los equivalentes SQL de C# DateTime.MaxValue y DateTime.MinValue.Búsqueda SQL para fecha entre valores o Min/Max si NULL

estoy pensando en usar Coalesce al igual que

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

¿Hay una función integrada/constante/variable de/enumeración que puedo usar para las variables <MinDateTime> y <MaxDateTime>?

¿Alguna sugerencia?

Respuesta

11

No existe tal funcionalidad en SQL Server. Puede encontrar fácilmente el min and max dates permitido en BOL (1753-01-01 - 9999-12-31). O podría codificar fácilmente otra fecha fácilmente (si realmente está trabajando con cumpleaños, 1800-01-01 - 2100-12-31 probablemente sería suficiente). O bien, podría (si se trata de la consulta gama has mostrado), tiene la coalescencia caer de nuevo a la misma fecha de nacimiento:

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

Pero tenga en cuenta que esto no necesariamente escalar bien para tablas muy grandes.

Editado después de aceptar, para responder a un comentario de OP

En general, para SQL, si usted está necesitando de datos "de referencia" con frecuencia, se añaden como una mesa de sí mismo. (Google para "tabla de calendario" o "tabla de números sql"). Así pues, en este caso, si quisiera, podría agregar un "constantes" (o tal vez la tabla "límites"):

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 

que luego se podría hacer referencia en las consultas (ya sea a través de una subselección, o mediante cruz de unión a esta mesa). P.ej.

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

(La cerradura, clave principal, y la restricción de comprobación, trabajar juntos para asegurar que sólo una única fila volverá a existir en esta tabla)

+0

Muy interesante. Nunca antes había visto el tipo de patrón Coalesce (@StartDate, Birthday). Creo que crear una variable llamada maxdate y mindate y establecer sus valores a las fechas de hardcoded podría ser mucho más legible. Pero sí, la información principal que estaba buscando era la falta de las enumeraciones/constantes en SQL – Chaitanya

+0

Truco Re COALESCE - +1 a la afirmación de que no se escalaría para tablas grandes, SQL Server no parece poder usar el índice en la columna de cumpleaños. Las fechas mínimas y máximas de codificación dura funcionan bien con el índice. –

3

No hay funciones integradas para obtener los valores de tiempo de fecha mínimo o máximo. Tienes que codificar los valores o recuperar los valores de la base de datos.

Si los parámetros son NULL, puede seleccionar las mínimas & de la tabla 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

no creo que esto es lo que quería decir Chaitanya. –

+0

+1 Puede que no sea exactamente lo que Chaitanya estaba pidiendo, pero cumple los requisitos lo suficientemente bien. No es necesario codificar en tiempo mínimo y máximo la misma fecha, y la misma consulta también se puede usar para casos nulos – InSane

4

Para SQL Server específicamente, de acuerdo con BOL, los límites son :

  • datetime: 01/01/1753 00:00:00 a través 9999-12-31 23: 59: 59.997
  • smalldatetime: 1900-01-01 00:00:00 a través de 2079-06- 06 23: 59: 29.998
  • date: 0001-01-01 hasta 9999-12-31
  • datetime2: 0001-01-01 00:00:00 hasta 9999-12-31 23:59:59.9999999

Como puede ver, depende de su tipo exacto de datos.

En cuanto a la consulta, lo haría así:

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

+1 para referencias. En cuanto a la consulta, es necesario probarla, 'ENTRE ... COALESCE' podría ser más comprensible para el planificador de consultas. – Unreason

Cuestiones relacionadas