🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

[¡Listo para Copiar y Pegar!] Guía Completa de la Función COUNT de SQL: Desde lo Básico hasta lo Avanzado

Al desarrollar sitios web o aplicaciones, a menudo surgen preguntas como: “¿Cuál es el número total de usuarios?” o “¿Cuántos tipos de productos hay en una categoría específica?” En estos casos, la función COUNT() de SQL es de gran utilidad.

COUNT() es una función de agregación que se utiliza para contar el número de registros (filas) en una tabla. A primera vista, parece sencilla, pero según cómo se utilice, puede extraer diversos tipos de información. Es una función sorprendentemente poderosa. En este artículo, explicaremos todo, desde el uso básico hasta aplicaciones prácticas, con muchos ejemplos de código “listos para copiar y pegar” para principiantes que aspiran a ser creadores web.

El objetivo de este artículo es ayudarte a experimentar la emoción de “¡SQL realmente funciona cuando lo escribo!”. ¡Dejemos la teoría complicada para después! Primero copia el código, ejecútalo y observa los resultados para descubrir lo divertido que puede ser SQL.


¡A calentar motores! Prepara datos de ejemplo

Para probar SQL, necesitas una tabla con algunos datos. En este caso, crearemos una tabla llamada users que simula una lista sencilla de usuarios. El siguiente SQL crea la tabla e inserta algunos datos de ejemplo.

Todo el código mostrado en este artículo utiliza esta tabla users como base.

-- Eliminar la tabla si existe (para poder probar varias veces)
DROP TABLE IF EXISTS users;

-- Crear la tabla users
CREATE TABLE users (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  prefecture TEXT NOT NULL,
  email TEXT
);

-- Insertar datos
INSERT INTO users (id, name, prefecture, email) VALUES
(1, 'Taro Yamada', 'Tokyo', 'yamada@example.com'),
(2, 'Hanako Suzuki', 'Osaka', 'suzuki@example.com'),
(3, 'Jiro Sato', 'Tokyo', NULL),
(4, 'Sakura Ito', 'Fukuoka', 'ito@example.com'),
(5, 'Saburo Watanabe', 'Hokkaido', 'watanabe@example.com'),
(6, 'Shiro Takahashi', 'Tokyo', 'takahashi@example.com'),
(7, 'Misaki Tanaka', 'Osaka', NULL);

Esta tabla contiene columnas para ID, nombre, prefectura y correo electrónico. Un punto clave es que los campos email de Sato (ID 3) y Tanaka (ID 7) están establecidos como NULL (es decir, vacíos). Esto será importante más adelante al explicar el comportamiento de la función COUNT().


[Básico 1] Contar todos los registros con `COUNT(*)`

Comencemos con el uso más básico: COUNT(*). El asterisco (*) significa “todas las columnas”, y COUNT(*) devuelve el número total de registros en la tabla. Se usa cuando simplemente quieres preguntar: “¿Cuántas entradas hay en esta tabla?”

Contemos ahora todos los usuarios de la tabla users.

SELECT COUNT(*) FROM users;

Resultado:

7

Como insertamos datos para 7 usuarios anteriormente, el resultado “7” es correcto. Esta es la base del uso de COUNT().


[Básico 2] Contar una columna específica con `COUNT(column_name)`

A continuación, veamos COUNT(column_name), que cuenta el número de registros que tienen un valor en la columna especificada.

Esto es importante: COUNT(column_name) ignora los valores NULL. Es decir, no cuenta los registros donde la columna está vacía.

Contemos cuántos usuarios tienen registrada una dirección de correo electrónico en la tabla users.

SELECT COUNT(email) FROM users;

Resultado:

5

El resultado es “5”. Es menos que los 7 de COUNT(*) porque los dos usuarios (Sato y Tanaka) que tienen NULL en la columna email fueron excluidos.

Así que recuerda: COUNT(*) da el número total de filas, mientras que COUNT(column_name) cuenta solo aquellas que tienen datos en esa columna.


[Avanzado 1] Asignar un alias al resultado con `AS`

Por defecto, el resultado de COUNT() aparece como COUNT(*) o COUNT(email), lo cual no es muy legible. Esto puede ser un inconveniente al manejar el resultado.

En estos casos, usa AS para asignar un alias (nombre más comprensible) a la columna de resultados.

SELECT COUNT(*) AS total_users FROM users;

Resultado:

total_users
-----------
7

Al agregar AS total_users, la columna de resultado se renombra como total_users. Así queda claro que representa el número total de usuarios. También es más fácil acceder al resultado en el código, por ejemplo: result['total_users'].


[Avanzado 2] Contar valores únicos con `COUNT(DISTINCT column_name)`

A continuación tenemos COUNT(DISTINCT), que se usa mucho en análisis web. La palabra clave DISTINCT significa “eliminar duplicados” y te permite contar el número de valores únicos.

Por ejemplo, podrías querer saber: “¿Desde cuántas prefecturas diferentes acceden los usuarios a este sitio?”

En la tabla users, hay 3 usuarios de Tokyo y 2 de Osaka. Contemos cuántas prefecturas distintas hay.

SELECT COUNT(DISTINCT prefecture) AS unique_prefectures FROM users;

Resultado:

unique_prefectures
------------------
4

El resultado es “4”. Las prefecturas en la tabla users son: Tokyo, Osaka, Fukuoka y Hokkaido—cuatro valores únicos.

Esto es útil en muchas situaciones: contar categorías de productos en un sitio de e-commerce, calcular el número de visitantes únicos a partir de los registros de acceso, etc.


[Avanzado 3] Contar por grupo con `GROUP BY`

COUNT() brilla aún más cuando se usa junto con la cláusula GROUP BY. Esta agrupa las filas que tienen el mismo valor en una columna especificada y aplica COUNT() a cada grupo.

¿Quieres saber cuántos usuarios hay por prefectura? Este es el caso perfecto para usar GROUP BY.

SELECT
  prefecture,
  COUNT(*) AS user_count
FROM
  users
GROUP BY
  prefecture;

Resultado:

prefecture | user_count
-----------|------------
Osaka      | 2
Hokkaido   | 1
Tokyo      | 3
Fukuoka    | 1

¡Perfecto! Obtenemos una lista con la cantidad de usuarios por prefectura. Se crean grupos a partir de la columna prefecture y se cuenta cuántas filas hay en cada grupo con COUNT(*).

Es una técnica esencial para el análisis web, por ejemplo para saber qué regiones tienen más usuarios.


[Consejo Pro] Filtrar resultados agregados con `HAVING`

A veces querrás filtrar los resultados después de agruparlos con GROUP BY. Por ejemplo: “mostrar solo prefecturas con dos o más usuarios”.

Atención: la cláusula WHERE filtra registros individuales antes de la agregación, por lo tanto no se puede usar para filtrar resultados agregados como user_count.

Para filtrar después de la agregación, usa la cláusula HAVING.

SELECT
  prefecture,
  COUNT(*) AS user_count
FROM
  users
GROUP BY
  prefecture
HAVING
  user_count >= 2;

Resultado:

prefecture | user_count
-----------|------------
Osaka      | 2
Tokyo      | 3

Al agregar HAVING user_count >= 2, se muestran solo las prefecturas con dos o más usuarios: Osaka y Tokyo.

Recuerda: WHERE se utiliza para filtrar registros individuales antes de la agregación, y HAVING se usa para filtrar los resultados después de GROUP BY.


[Esquina Interactiva] ¡Prueba SQL en tu navegador!

¡Gracias por esperar! Aquí hemos preparado un entorno donde puedes ejecutar el SQL que has aprendido con tus propias manos.

Copie todo el código HTML siguiente, guárdelo como un archivo con un nombre como sql_test.html y ábralo en tu navegador. La tabla users introducida en este artículo ya está preparada, así que prueba varias sentencias SQL y disfruta viendo cómo cambian los resultados.

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Entorno de ejecución SQL para COUNT()</title>
  <style>
    body { font-family: sans-serif; line-height: 1.6; color: #333; max-width: 800px; margin: 2rem auto; padding: 0 1rem; }
    h1 { color: #444; }
    textarea { width: 100%; height: 150px; font-family: monospace; font-size: 16px; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-bottom: 1rem; }
    button { background-color: #007bff; color: white; border: none; padding: 10px 20px; font-size: 16px; border-radius: 4px; cursor: pointer; }
    button:hover { background-color: #0056b3; }
    button:disabled { background-color: #ccc; cursor: not-allowed; }
    #result-container { margin-top: 2rem; border: 1px solid #ddd; padding: 1rem; border-radius: 4px; background: #f9f9f9; min-height: 50px; }
    #error-message { color: #d9534f; font-weight: bold; }
    table { border-collapse: collapse; width: 100%; margin-top: 1rem; }
    th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
    th { background-color: #f2f2f2; }
  </style>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/sql-wasm.js"></script>
</head>
<body>

  <h1>¡Prueba SQL!</h1>
  <p>Introduce SQL en el área de texto de abajo y haz clic en el botón "Ejecutar". ¡Prueba los diversos ejemplos de SQL presentados en este artículo!</p>

  <textarea id="sql-input">SELECT prefecture, COUNT(*) AS user_count
FROM users
GROUP BY prefecture
HAVING user_count >= 2;</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...';
      try {
        const SQL = await initSqlJs({
          locateFile: file => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/${file}`
        });
        db = new SQL.Database();
        
        // Configurar tabla inicial y datos
        const setupSql = `
          DROP TABLE IF EXISTS users;
          CREATE TABLE users (
            id INTEGER PRIMARY KEY,
            name TEXT NOT NULL,
            prefecture TEXT NOT NULL,
            email TEXT
          );
          INSERT INTO users (id, name, prefecture, email) VALUES
          (1, 'Taro Yamada', 'Tokyo', 'yamada@example.com'),
          (2, 'Hanako Suzuki', 'Osaka', 'suzuki@example.com'),
          (3, 'Jiro Sato', 'Tokyo', NULL),
          (4, 'Sakura Ito', 'Fukuoka', 'ito@example.com'),
          (5, 'Saburo Watanabe', 'Hokkaido', 'watanabe@example.com'),
          (6, 'Shiro Takahashi', 'Tokyo', 'takahashi@example.com'),
          (7, 'Misaki Tanaka', 'Osaka', NULL);
        `;
        db.run(setupSql);
        
        executeBtn.disabled = false;
        executeBtn.textContent = 'Ejecutar';
        resultOutput.innerHTML = '<p>¡Listo! Introduce tu SQL y haz clic en Ejecutar.</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>La consulta se ejecutó correctamente pero no devolvió conjunto de resultados (por ejemplo, INSERT, UPDATE, etc.).</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>

【¡Pruébalo tú mismo!】


Puntos a tener en cuenta y curiosidades

COUNT(*) vs COUNT(1) vs COUNT(column_name)

Es posible que veas la sintaxis COUNT(1). Esto significa que se asigna la constante “1” a cada fila y luego se cuenta. En la mayoría de las bases de datos, no hay diferencia en comportamiento ni rendimiento entre COUNT(*) y COUNT(1); ambos cuentan todas las filas. En cambio, COUNT(column_name) no cuenta los valores NULL, como se explicó antes, por lo que su propósito es distinto. Si tienes dudas, utiliza COUNT(*) si deseas contar todas las filas, o COUNT(column_name) si deseas contar solo las que no sean NULL.

Rendimiento

Ejecutar COUNT(*) en una tabla enorme con millones o decenas de millones de registros puede tardar bastante, especialmente si estás contando todos los registros sin ninguna condición, ya que se debe escanear toda la tabla. Si necesitas obtener frecuentemente el total de registros, podrías considerar métodos alternativos como usar tablas resumen, pero por ahora es suficiente entender su uso básico.


Funciones relacionadas: otras funciones de agregación

Una vez que aprendes COUNT(), aprender otras funciones de agregación es fácil. Estas se vuelven aún más potentes cuando se combinan con GROUP BY.

Por ejemplo, para conocer el valor máximo del ID de usuario, puedes hacer lo siguiente:

SELECT MAX(id) AS latest_user_id FROM users;

Resumen

En este artículo, hemos revisado rápidamente la función COUNT() para contar registros, desde su uso básico hasta técnicas avanzadas.

COUNT() es un paso fundamental para analizar datos. Prueba varias veces los códigos de este artículo y adquiere la sensación de “contar datos”. Una vez que domines SQL, tu capacidad para analizar datos se ampliará enormemente. ¡Sigue aprendiendo con entusiasmo!