Los sistemas modernos de BI y CRM a menudo requieren implementar filtros personalizados: es importante combinar flexiblemente condiciones arbitrarias (por fecha, género, estado, etiquetas), así como cruzarlas y unirlas correctamente en SQL. El código resultante debe ser legible, fácilmente modificable y producir resultados esperados.
A menudo, los desarrolladores forman "sobre la marcha" un WHERE con muchas AND/OR de los filtros personalizados, lo que lleva a errores lógicos y consultas de difícil mantenimiento. El problema se agrava si los valores de los filtros pueden estar ausentes o combinarse con IN/EXISTS/LIKE.
Para filtros dinámicos, es conveniente el patrón "condición con OR siempre TRUE si el valor no está definido":
SELECT * FROM users WHERE (status = @status OR @status IS NULL) AND (gender = @gender OR @gender IS NULL) AND (created >= @from_date OR @from_date IS NULL) AND (city IN (@cities) OR @cities IS NULL);
O utilizando SQL dinámico:
DECLARE @sql NVARCHAR(MAX) = N'SELECT * FROM users WHERE 1=1'; IF @status IS NOT NULL SET @sql += N' AND status = @status'; IF @gender IS NOT NULL SET @sql += N' AND gender = @gender'; -- ... EXEC sp_executesql @sql, N'@status NVARCHAR(10),@gender NVARCHAR(10)', @status, @gender;
Características clave:
¿Se puede usar WHERE 1=1 en todas partes en lugar de verificar la existencia de condiciones?
No, 1=1 es solo una condición inicial para la concatenación de WHERE; no reemplaza filtros, solo se utiliza para facilitar la generación de consultas.
¿Qué problemas pueden surgir si IN() recibe una lista vacía?
IN (NULL) o IN() siempre devuelve false y produce un conjunto vacío, incluso en ausencia de filtro. Para un funcionamiento correcto, se debe verificar por separado si la lista está vacía y no incluir la condición en absoluto.
¿Cómo afectarán tales construcciones al uso de índices y al rendimiento?
Si los filtros se implementan con OR o comprobaciones de NULL, muchas bases de datos dejarán de utilizar índices de manera efectiva o se escaneará toda la tabla. Se recomienda aplicar enfoques con SQL dinámico o filtros mediante consultas parametrizadas para que el planificador pueda elegir el índice.
Un informe clásico con 10 filtros, el código genera WHERE con múltiples OR; cuando faltan varios filtros, el resultado es un conjunto vacío o un escaneo demasiado grande, lo que aumenta la carga en el servidor exponencialmente.
Ventajas:
Una función separada genera filtros solo para los parámetros dados, y solo para cada grupo de condiciones se incluye un JOIN/FILTER separado. Where no contiene OR ni comprobaciones innecesarias de NULL.
Ventajas: