【Cláusula BETWEEN de SQL】¡Domina las Búsquedas por Rango! Una Forma Inteligente de Especificar Rangos para Números y Fechas
En el desarrollo de sitios web y aplicaciones, es muy común necesitar extraer datos que se encuentran dentro de un cierto rango, como "productos con un precio entre 10 y 50 euros" o "usuarios que se registraron entre el 1 y el 30 de junio".
Al escribir una condición de este tipo en una cláusula WHERE, ¿cómo lo harías?
WHERE price >= 1000 AND price <= 5000
Así, usando operadores de comparación (>=, <=) y AND, por supuesto que puedes especificar un rango. Sin embargo, SQL proporciona un comando dedicado para hacer esta "búsqueda por rango" más intuitiva y limpia. Ese es nuestro tema principal de hoy: la cláusula BETWEEN.
Este artículo explicará a fondo todo, desde el uso básico de la cláusula BETWEEN, hasta su aplicación con rangos de fechas, y su forma negativa, NOT BETWEEN, todo con código que puedes copiar y pegar. ¡Dejemos atrás las engorrosas cadenas de operadores de comparación y adquiramos la habilidad de escribir SQL inteligente y fácil de leer para todos!
Preparación: Preparemos Nuestros Datos de Pedidos para la Búsqueda
Para probar las búsquedas por rango, primero necesitamos algunos datos con los que trabajar. Esta vez, crearemos una tabla de orders que imita el historial de pedidos de un sitio de comercio electrónico. Al incluir datos con varios rangos de precios y fechas de pedido, será más fácil apreciar los efectos de la cláusula BETWEEN.
-- Si la tabla orders existe, eliminarla (para pruebas repetibles)
DROP TABLE IF EXISTS orders;
-- Crear una nueva tabla orders
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
product_name TEXT NOT NULL,
price INTEGER NOT NULL,
order_date DATE NOT NULL,
quantity INTEGER NOT NULL
);
-- Insertar datos iniciales
INSERT INTO orders (id, product_name, price, order_date, quantity) VALUES
(1, 'Bolígrafo Asombroso', 200, '2025-06-05', 3),
(2, 'Cuaderno Mágico', 500, '2025-06-10', 5),
(3, 'Arrocera Definitiva', 30000, '2025-06-15', 1),
(4, 'Manzana Milagrosa', 980, '2025-06-20', 10),
(5, 'Hub USB-C', 4500, '2025-06-25', 2),
(6, 'Pincel Tradicional', 12000, '2025-06-30', 1),
(7, 'Chocolate Premium', 3500, '2025-07-01', 4);
Ahora estamos listos para extraer datos usando varios rangos.
【Lo Básico】Especificando un Rango Numérico con la Cláusula BETWEEN
La sintaxis básica de la cláusula BETWEEN es muy clara.
WHERE nombre_columna BETWEEN valor_mínimo AND valor_máximo;
El punto más importante aquí es que el rango para la cláusula `BETWEEN` es inclusivo, lo que significa que incluye tanto los valores mínimo como máximo especificados. En otras palabras, WHERE price BETWEEN 1000 AND 5000 significa exactamente lo mismo que WHERE price >= 1000 AND price <= 5000. Asegúrate de recordar este punto de que "incluye ambos extremos".
Escenario: "Encontrar todos los productos con un precio entre 1,000 y 5,000."
SELECT * FROM orders
WHERE price BETWEEN 1000 AND 5000;
Resultado:
id | product_name | price | order_date | quantity
---|-------------------|-------|------------|----------
5 | Hub USB-C | 4500 | 2025-06-25 | 2
7 | Chocolate Premium | 3500 | 2025-07-01 | 4
El código es más limpio que usar dos operadores de comparación, y la intención de "un rango de 1,000 a 5,000" se transmite más directamente, ¿no crees?
【Aplicación】Especificando un Rango de Fechas con la Cláusula BETWEEN
Una característica conveniente de la cláusula BETWEEN es que se puede usar no solo para números, sino también para especificar rangos de fechas (tipo DATE) y fecha y hora (tipo DATETIME). Dado que los requisitos para extraer datos de un período específico son muy comunes en las aplicaciones web, esta es una técnica de uso frecuente.
Escenario: "Encontrar todos los pedidos realizados durante junio de 2025."
En este caso, especificamos el inicio del rango como "2025-06-01" y el final como "2025-06-30".
SELECT * FROM orders
WHERE order_date BETWEEN '2025-06-01' AND '2025-06-30';
Resultado:
id | product_name | price | order_date | quantity
---|-----------------------|-------|------------|----------
1 | Bolígrafo Asombroso | 200 | 2025-06-05 | 3
2 | Cuaderno Mágico | 500 | 2025-06-10 | 5
3 | Arrocera Definitiva | 30000 | 2025-06-15 | 1
4 | Manzana Milagrosa | 980 | 2025-06-20 | 10
5 | Hub USB-C | 4500 | 2025-06-25 | 2
6 | Pincel Tradicional | 12000 | 2025-06-30 | 1
Como puedes ver, los pedidos del 1 de junio y del 30 de junio están correctamente incluidos en el resultado. Esto también se debe a la naturaleza "inclusiva de ambos extremos" de la cláusula BETWEEN.
【La Condición Opuesta】Especificando lo que está Fuera de un Rango con NOT BETWEEN
Si quieres encontrar cosas que están **fuera** de un rango especificado, usas la cláusula NOT BETWEEN.
Hay un punto a tener en cuenta aquí. Mientras que price BETWEEN 1000 AND 5000 significaba "mayor o igual a 1000 Y menor o igual a 5000", price NOT BETWEEN 1000 AND 5000 significa "menor que 1000 **O** mayor que 5000" (price < 1000 OR price > 5000). En otras palabras, los propios valores límite no se incluyen en el resultado.
Escenario: "Encontrar todos los productos que son o muy baratos (menos de 1,000) o muy caros (más de 5,000)."
SELECT * FROM orders
WHERE price NOT BETWEEN 1000 AND 5000;
Resultado:
id | product_name | price | order_date | quantity
---|-----------------------|-------|------------|----------
1 | Bolígrafo Asombroso | 200 | 2025-06-05 | 3
2 | Cuaderno Mágico | 500 | 2025-06-10 | 5
3 | Arrocera Definitiva | 30000 | 2025-06-15 | 1
4 | Manzana Milagrosa | 980 | 2025-06-20 | 10
6 | Pincel Tradicional | 12000 | 2025-06-30 | 1
Aunque nuestros datos de muestra no tienen productos con un precio de exactamente 1,000 o 5,000, recuerda que incluso si existieran, no se incluirían en este resultado.
【Patio de Recreo Interactivo】¡Domina las Búsquedas por Rango Ejecutando SQL en tu Navegador!
¡Ahora, es el momento de convertir el conocimiento en una habilidad! Copia todo el código HTML a continuación, guárdalo como un archivo llamado sql_between_test.html y ábrelo en tu navegador. Se iniciará tu propio entorno SQL personal, precargado con la tabla orders que hemos estado usando en este artículo.
Prueba a cambiar los rangos numéricos o de fechas para familiarizarte con la naturaleza "inclusiva de ambos extremos" de la cláusula BETWEEN. ¡Prueba también NOT BETWEEN y mira cómo cambian los resultados!
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Patio de Recreo en Línea de la Cláusula BETWEEN de SQL</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; line-height: 1.7; color: #333; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
h1 { color: #16a085; }
textarea { width: 100%; height: 180px; font-family: "SF Mono", "Consolas", monospace; font-size: 16px; padding: 12px; border: 1px solid #ccc; border-radius: 6px; box-sizing: border-box; margin-bottom: 1rem; }
button { background-color: #1abc9c; color: white; border: none; padding: 12px 22px; font-size: 16px; border-radius: 6px; cursor: pointer; transition: background-color 0.2s; }
button:hover { background-color: #16a085; }
button:disabled { background-color: #bdc3c7; cursor: not-allowed; }
#result-container { margin-top: 2rem; border: 1px solid #ddd; padding: 1rem; border-radius: 6px; background: #fdfdfd; min-height: 50px; }
#error-message { color: #e74c3c; font-weight: bold; }
table { border-collapse: collapse; width: 100%; margin-top: 1rem; }
th, td { border: 1px solid #ddd; padding: 10px; text-align: left; }
th { background-color: #f2f2f2; }
tr:nth-child(even) { background-color: #f9f9f9; }
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/sql-wasm.js"></script>
</head>
<body>
<h1>¡Probemos SQL!</h1>
<p>Introduce una sentencia SQL en el área de texto de abajo y haz clic en el botón "Ejecutar". ¡Prueba con diferentes rangos!</p>
<textarea id="sql-input">-- Encontrar pedidos realizados entre el 10 y el 25 de junio
SELECT * FROM orders
WHERE order_date BETWEEN '2025-06-10' AND '2025-06-25';
</textarea>
<button id="execute-btn">Ejecutar</button>
<div id="result-container">
<p id="error-message"></p>
<div id="result-output"></div>
</div>
<script>
const sqlInput = document.getElementById('sql-input');
const executeBtn = document.getElementById('execute-btn');
const errorMsg = document.getElementById('error-message');
const resultOutput = document.getElementById('result-output');
let db;
async function initDb() {
executeBtn.disabled = true;
executeBtn.textContent = 'Inicializando BD...';
try {
const SQL = await initSqlJs({
locateFile: file => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/${file}`
});
db = new SQL.Database();
const setupSql = `
DROP TABLE IF EXISTS orders;
CREATE TABLE orders (id INTEGER PRIMARY KEY, product_name TEXT NOT NULL, price INTEGER NOT NULL, order_date DATE NOT NULL, quantity INTEGER NOT NULL);
INSERT INTO orders (id, product_name, price, order_date, quantity) VALUES
(1, 'Bolígrafo Asombroso', 200, '2025-06-05', 3),
(2, 'Cuaderno Mágico', 500, '2025-06-10', 5),
(3, 'Arrocera Definitiva', 30000, '2025-06-15', 1),
(4, 'Manzana Milagrosa', 980, '2025-06-20', 10),
(5, 'Hub USB-C', 4500, '2025-06-25', 2),
(6, 'Pincel Tradicional', 12000, '2025-06-30', 1),
(7, 'Chocolate Premium', 3500, '2025-07-01', 4);
`;
db.run(setupSql);
executeBtn.disabled = false;
executeBtn.textContent = 'Ejecutar';
resultOutput.innerHTML = '<p>¡Todo listo! Siéntete libre de probar tus propias consultas SQL.</p>';
} catch (err) {
errorMsg.textContent = 'Error al inicializar la base de datos: ' + err.message;
console.error(err);
}
}
function executeSql() {
if (!db) return;
const sql = sqlInput.value;
errorMsg.textContent = '';
resultOutput.innerHTML = '';
try {
const results = db.exec(sql);
if (results.length === 0) {
resultOutput.innerHTML = '<p>Consulta ejecutada con éxito, pero no se devolvió ningún conjunto de resultados.</p>';
return;
}
results.forEach(result => {
const table = document.createElement('table');
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');
const headerRow = document.createElement('tr');
result.columns.forEach(colName => {
const th = document.createElement('th');
th.textContent = colName;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
result.values.forEach(row => {
const bodyRow = document.createElement('tr');
row.forEach(cellValue => {
const td = document.createElement('td');
td.textContent = cellValue === null ? 'NULL' : cellValue;
bodyRow.appendChild(td);
});
tbody.appendChild(bodyRow);
});
table.appendChild(thead);
table.appendChild(tbody);
resultOutput.appendChild(table);
});
} catch (err) {
errorMsg.textContent = 'Error de SQL: ' + err.message;
console.error(err);
}
}
executeBtn.addEventListener('click', executeSql);
initDb();
</script>
</body>
</html>
Puntos a Tener en Cuenta: Manejo de Fecha y Hora y Orden de los Valores
Aunque la cláusula BETWEEN es simple y poderosa, hay algunos puntos a tener en cuenta.
- Orden de los Valores: Cuando escribes
BETWEEN A AND B, siempre debes especificar el valor más pequeño para A y el valor más grande para B. Si inviertes el orden, comoBETWEEN 5000 AND 1000, no coincidirá con ningún registro, aunque existan datos dentro de ese rango. Asegúrate siempre de escribirlo en el orden de "valor mínimo Y valor máximo". - Manejo de Fecha y Hora (tipo TIMESTAMP, etc.): Debes tener especial cuidado al usar
BETWEENcon columnas que incluyen la hora (p. ej., `YYYY-MM-DD HH:MM:SS`). Por ejemplo, si especificasorder_datetime BETWEEN '2025-06-01' AND '2025-06-30', esto se interpreta internamente como hasta `'2025-06-30 00:00:00'`. Como resultado, un pedido realizado en la tarde del 30 de junio (p. ej., '2025-06-30 15:00:00') quedaría fuera del rango y no se incluiría en los resultados. Si quieres incluir todo el día 30 de junio, la forma fiable es especificar la hora explícitamente, comoBETWEEN '2025-06-01 00:00:00' AND '2025-06-30 23:59:59', o usar operadores de comparación para especificar "antes del inicio del día siguiente", comoorder_datetime >= '2025-06-01' AND order_datetime < '2025-07-01'.
Conclusión
En este artículo, hemos aprendido sobre la cláusula BETWEEN, que permite realizar búsquedas por rango de números y fechas de forma intuitiva.
- Sintaxis Básica:
WHERE nombre_columna BETWEEN valor_mínimo AND valor_máximo. Es más legible que usar operadores de comparación (>= ... AND <= ...). - El Rango es Inclusivo: Este es el punto más importante: la cláusula
BETWEENse evalúa como "mayor o igual que Y menor o igual que". - `NOT BETWEEN`: Extrae datos fuera del rango. Este se evalúa como "menor que O mayor que" y no incluye los valores límite.
- También para Fechas: Al especificar cadenas en el formato
'YYYY-MM-DD', puedes realizar fácilmente búsquedas por rango de fechas. - Consideraciones Clave: Escribe siempre en el orden de "mínimo Y máximo", y ten en cuenta que se necesita un cuidado especial para especificar rangos para columnas que incluyen la hora.
Al dominar la cláusula BETWEEN, el SQL que escribas se volverá más simple y su intención más clara. ¡Da un paso más allá de las simples combinaciones de operadores de comparación y añade una técnica de extracción de datos más refinada a tu caja de herramientas!