Saltar al contenido

Usando GROUP BY WITH ROLLUP en la columna que contiene NULL

Solución:

tienes una “solución”, así que al decir

Me pregunto si existe una solución mejor.

Creo que quieres comentarlo. Permítanme centrarme en varios aspectos:

  1. SELECT ID [...] GROUP BY word, independientemente de tener o no un WITH ROLLUP Está Mal. Estás seleccionando un campo cuyo valor es indeterminado. En particular, con MySQL se expone a devolver un valor aleatorio; o si usa un modo estricto (recomendado, y por defecto en las últimas versiones de MySQL), la consulta fallará: ‘db_9_b0ff7.test.ID’ no está en GROUP BY

  2. Ya sea formalmente o no, WITH ROLLUP Nota: (me refiero a la implementación de MySQL) es algo que es bueno tener en algunos casos porque evita una doble exploración de la tabla, pero no he visto mucho en el código de producción. No tiene nada de malo, pero eran una función exclusiva de MSSQL hasta que se implementó en SQL1999, y no estaba disponible ampliamente en el pasado o, como en el caso de MySQL fue una implementación limitada. Referencia: https://www.percona.com/blog/2007/09/17/using-group-by-with-rollup-for-reporting-performance-optimization/

  3. No veo en principio un problema con su consulta final, si ejecutamos explicar en ambas consultas (sin ID), vemos:

    MariaDB [test]> EXPLAIN SELECT   if(count(word) = 0, "empty", ifnull(word, "total")) as word,   count(*) as occurrences FROM test group by word with ROLLUPG
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: test
             type: ALL
    possible_keys: NULL
              key: NULL
          key_len: NULL
              ref: NULL
             rows: 4
            Extra: Using filesort
    1 row in set, 1 warning (0.00 sec)
    
    Warning (Code 1052): Column 'word' in group statement is ambiguous
    MariaDB [test]> EXPLAIN SELECT   ifnull(word, "total") as word,   count(*) as occurrences FROM ( SELECT   ifnull(word, "empty") as word FROM test ) tmp GROUP BY word WITH ROLLUPG
    *************************** 1. row ***************************
               id: 1
      select_type: SIMPLE
            table: test
             type: ALL
    possible_keys: NULL
              key: NULL
          key_len: NULL
              ref: NULL
             rows: 4
            Extra: Using filesort
    1 row in set, 1 warning (0.01 sec)
    

    Normalmente, el odio hacia MySQL se debe a sus limitaciones en las primeras versiones de MySQL. No voy a decir que ahora sea perfecto, todavía habrá problemas, ya que el desarrollo de MySQL, como siempre ha sido, se centró en un RDBMS rápido, fácil de entrar y salir, y no en un motor relacional en toda regla. , pero una subconsulta en el lugar correcto está bien (después de todo, algunas consultas requerirán una subconsulta, pase lo que pase. Tu uso está bien– solo tendrá una sobrecarga de repasar las filas resumidas nuevamente y supongo que en el trato real, esas no serán significativas en comparación con el conjunto completo.

    Nota: en mi instancia aquí arriba, la subconsulta no se muestra, pero puede verla con subconsultas materializadas en 5.6 aquí: http://sqlfiddle.com/#!9/b0ff7/7 (Ejecutará la consulta interna y luego la parte exterior, sin problema). Un índice definitivamente podría ayudar aquí (debido a la clasificación de archivos), pero eso depende del número final de registros. La subconsulta puede perjudicar el rendimiento si un índice (que no existe ahora) no se puede utilizar porque. Debe probar su versión específica de mysql y crear dicho índice.

  4. Creo que su problema es con el modelo de datos: en el mundo SQL (fuera de Oracle) NULL es un valor desconocido / no válido. Parece estar correlacionando eso con ‘vacío’, lo cual no es correcto; si se sabe que una palabra no existe, debería ser ” (la cadena vacía, no NULL). No se si puedes cambiar eso, pero No me gusta tu modelo actual. Entiendo que es posible que no tenga algo que decir al respecto, así que no me centraré en eso. ¿También cuentas palabras NULAS? Más razones para usar ” en lugar de NULL.
  5. Ahora la pregunta final es, ¿es posible hacerlo sin una subconsulta en MySQL, y será mejor / menos feo? Realmente no veo un camino– podríamos hacer una unión, pero seguirá siendo una subconsulta. Puedo pensar en una alternativa, que es:

    SELECT * FROM (
        SELECT   word,   
        count(*) as occurrences 
        FROM test 
        GROUP BY word with rollup) 
    tmp 
    ORDER BY occurrences;
    

    Eso asegura que la última fila contenga el resumen (y si hay otro nulo, es el valor nulo real). El orden ocurriría incluso en el caso de solo valores nulos. Por el contrario, es posible que sea incluso más lento, ya que requiere un pedido y, nuevamente, es posible que necesite un índice, y ese índice puede o no usarse.

Puede evitar las subconsultas y optimizar los caracteres escritos con esta consulta:

SELECT
  ifnull(word, "empty") as word,
  count(*) as occurrences
FROM test
GROUP BY ifnull(word, "empty") WITH ROLLUP
;

Esto básicamente reemplaza null valores con su marcador “vacío” antes de realizar la agrupación:

  • los recuentos nulos se pueden encontrar en la fila que contiene el valor “vacío” en la columna de agrupación
  • los recuentos totales se pueden encontrar en la fila que contiene null valor en la columna de agrupación

Se puede utilizar un enfoque similar para PostgreSQL, esto no debería ser necesario para SQL Server ya que proporciona un GROUPING función.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *