Cargando aplicación...
Preparando tu experiencia meskeIA
Aprende SQL practicando en el navegador. Sin instalar nada, 100% privado.
⏳ Cargando base de datos...
Conceptos clave y referencia rápida
SQL es un estándar, pero cada motor de base de datos tiene sus propias particularidades. Esta tabla te ayuda a entender las diferencias clave para escribir código portable o adaptarte rápidamente al motor que uses en cada proyecto.
| Criterio | SQLite | MySQL 8 | PostgreSQL 16 | SQL Server 2022 |
|---|---|---|---|---|
| Licencia | Dominio público | GPL/Comercial | PostgreSQL (libre) | Propietario |
| Instalación | Sin servidor | Servidor dedicado | Servidor dedicado | Servidor dedicado |
| Auto-increment | INTEGER PRIMARY KEY | AUTO_INCREMENT | SERIAL / GENERATED | IDENTITY |
| Tipo booleano | INTEGER (0/1) | TINYINT(1) / BOOL | BOOLEAN nativo | BIT |
| Concatenar strings | || | CONCAT() o || | || o CONCAT() | + o CONCAT() |
| LIMIT/OFFSET | LIMIT n OFFSET m | LIMIT n OFFSET m | LIMIT n OFFSET m | TOP n / FETCH NEXT |
| JSON nativo | Sí (básico) | Sí (JSON type) | Sí (JSONB avanzado) | Sí (JSON functions) |
| Ideal para | Aprendizaje, apps pequeñas | Web, WordPress, e-commerce | Sistemas complejos, BI | Empresas Microsoft |
Dominar JOINs para evitar N+1 queries. Un bucle que hace 1 query por fila = 1000 queries para 1000 filas. Un JOIN bien hecho = 1 query.
SELECT u.nombre, COUNT(p.id) FROM usuarios u LEFT JOIN pedidos p ON u.id = p.usuario_id GROUP BY u.idRendimiento crítico
GROUP BY + funciones de ventana (WINDOW FUNCTIONS) para KPIs. Reportes de cohortes, retención y LTV.
ROW_NUMBER() OVER ( PARTITION BY categoria ORDER BY ventas DESC )Ranking por categoría
Optimización con índices. EXPLAIN ANALYZE en PostgreSQL o EXPLAIN en MySQL para ver el plan de ejecución. Un índice reduce de O(n×m) a O(log n).
EXPLAIN ANALYZE SELECT * FROM pedidos WHERE cliente_id = 42;Plan de ejecución
Modelado entidad-relación. Normalización (1FN, 2FN, 3FN). Transacciones ACID. SQL es obligatorio en casi todos los currículos de CS e Ingeniería Informática.
Base imprescindibleConsultas de inventario, pedidos y clientes. Calcular totales con JOINs y HAVING para filtrar resultados.
SELECT p.nombre, SUM(dp.cantidad * dp.precio) AS total FROM pedidos o JOIN detalle_pedido dp ON o.id = dp.pedido_id GROUP BY o.id HAVING total > 100Pedidos y facturación
Logs de acceso y detección de anomalías. Detectar ataques de fuerza bruta con GROUP BY + HAVING.
SELECT usuario_id, COUNT(*) FROM logs_acceso WHERE fecha > NOW() - INTERVAL '1 hour' GROUP BY usuario_id HAVING COUNT(*) > 100Detección de ataques
WHERE filtra filas ANTES de agrupar (afecta a datos originales). HAVING filtra grupos DESPUÉS de GROUP BY. Ejemplo: WHERE precio > 10 filtra productos antes de contar; HAVING COUNT(*) > 5 filtra categorías que tienen más de 5 productos.
INNER JOIN devuelve solo filas con coincidencia en ambas tablas (descarta filas sin match). LEFT JOIN devuelve todas las filas de la tabla izquierda más coincidencias (NULL donde no hay match). Regla práctica: usa LEFT JOIN cuando quieras "todos los X con sus Y opcionales".
Una subconsulta es un SELECT dentro de otro SELECT. Es mejor para: filtrar con condiciones complejas, verificar existencia (EXISTS) o cuando el resultado es escalar. Un JOIN es más eficiente cuando necesitas columnas de ambas tablas y el optimizador puede usar índices.
SQL estándar no permite SELECT de columnas que no estén en GROUP BY ni en funciones de agregación. MySQL en modo permisivo lo permite (elige valor arbitrario). PostgreSQL y SQLite son estrictos. Solución: añadir la columna al GROUP BY o usar MAX(columna).
El índice es como el índice de un libro: evita leer toda la tabla. Créalo en: columnas usadas en WHERE frecuentemente, columnas de JOIN (claves foráneas) y columnas de ORDER BY con muchas filas. No lo crees en: tablas pequeñas, columnas con pocos valores distintos (booleanos) o columnas que se actualizan constantemente.
DELETE elimina filas con WHERE, activa triggers y es más lento. TRUNCATE elimina TODAS las filas, es más rápido, sin triggers y no disponible en SQLite básico. DROP elimina la tabla completa con su estructura. DELETE es reversible en transacción; TRUNCATE/DROP pueden no serlo.
Garantizan ACID: Atomicidad (todo o nada), Consistencia, Aislamiento y Durabilidad. Ejemplo: en una transferencia bancaria, debitar cuenta A y acreditar cuenta B deben ocurrir juntos o ninguna.BEGIN; UPDATE ...; UPDATE ...; COMMIT;
NUNCA concatenar strings del usuario en queries. Usa prepared statements/parameterized queries:SELECT * FROM usuarios WHERE email = ? con el valor como parámetro separado. En ORMs (Sequelize, Hibernate) esto es automático. En SQL puro: siempre usa placeholders.
"Quiero el top 5 de clientes con más gasto en el último mes". Escríbelo en palabras antes de escribir código.
Clientes, pedidos, detalle_pedido. Dibuja las relaciones o consulta el tab Esquema de este playground para visualizarlas.
Conecta las tablas por sus claves foráneas. Empieza por la tabla principal y añade JOINs uno a uno hasta completar el grafo de relaciones.
Solo las filas del último mes: WHERE fecha_pedido >= DATE('now', '-30 days')
GROUP BY cliente_id + SUM(cantidad * precio_unitario) AS total_gastado
ORDER BY total_gastado DESC LIMIT 5
Comprueba que el resultado tiene sentido. Prueba con LIMIT 1 primero para ver la estructura antes de expandir.
SELECT u.nombre AS cliente, COUNT(p.id) AS num_pedidos mejora la legibilidad enormemente.
Evita SELECT * en producción. Lista las columnas que necesitas, reduces datos transferidos y evitas errores si se añaden columnas nuevas.
Siempre crea índice en columnas usadas en JOINs. MySQL no lo hace automático (PostgreSQL sí en PKs). CREATE INDEX idx_pedidos_cliente ON pedidos(cliente_id)
Antes de ejecutar una query en tabla grande, añade LIMIT 10. Evita bloqueos y resultados interminables.
-- Clientes activos con más de 5 pedidos en el último trimestre. Los comentarios SQL sobreviven en logs y ayudan al siguiente desarrollador.
En PostgreSQL: EXPLAIN ANALYZE tu_query. En MySQL: EXPLAIN tu_query. Muestra si usa índices o hace full table scan.
"SELECT * FROM usuarios WHERE nombre = '" + input + "'" permite destruir la base de datos. Usa prepared statements SIEMPRE.DELETE FROM productos elimina TODOS los productos. Siempre verifica con SELECT antes de DELETE. Haz backup en producción.SQL (Structured Query Language) es el lenguaje estándar para consultar y manipular bases de datos relacionales. Aquí tienes una referencia rápida de los comandos más utilizados.
SELECT columna1, columna2 FROM tabla WHERE condicion ORDER BY columna LIMIT n;
SELECT a.*, b.columna FROM tabla_a a JOIN tabla_b b ON a.id = b.tabla_a_id;
SELECT categoria, COUNT(*) FROM productos GROUP BY categoria HAVING COUNT(*) > 5;
COUNT(*) - Contar filas SUM(col) - Sumar valores AVG(col) - Promedio MIN(col) - Mínimo MAX(col) - Máximo
=, !=, <, >, <=, >= AND, OR, NOT BETWEEN x AND y IN (valor1, valor2) LIKE 'patron%' IS NULL, IS NOT NULL
SELECT * FROM productos WHERE precio > ( SELECT AVG(precio) FROM productos );
Devuelve solo las filas que tienen coincidencia en ambas tablas.
Devuelve todas las filas de la tabla izquierda y las coincidencias de la derecha (NULL si no hay).
Devuelve todas las filas de la tabla derecha y las coincidencias de la izquierda.
Devuelve todas las filas de ambas tablas, con NULL donde no hay coincidencia.