Tengo un informe que muestra el recuento de eventos de las últimas 12 horas, agrupados por hora. Suena bastante fácil, pero con lo que estoy luchando es cómo incluir registros que cubran las brechas.
Aquí hay una tabla de ejemplo:
Event
(
EventTime datetime,
EventType int
)
Los datos se ven así:
'2012-03-08 08:00:04', 1
'2012-03-08 09:10:00', 2
'2012-03-08 09:11:04', 2
'2012-03-08 09:10:09', 1
'2012-03-08 10:00:17', 4
'2012-03-08 11:00:04', 1
Necesito crear un conjunto de resultados que tenga un registro por cada hora de las últimas 12 horas, independientemente de que haya eventos durante esa hora o no.
Suponiendo que la hora actual es '2012-03-08 11:00:00', el informe mostraría (aproximadamente):
Hour EventCount
---- ----------
23 0
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 1
9 3
10 1
Se me ocurrió una solución que utiliza una tabla que tiene un registro para cada hora del día. Logré obtener los resultados que estaba buscando usando UNION y alguna lógica de caso complicada en la cláusula where, pero esperaba que alguien tuviera una solución más elegante.
fuente
Las tablas de conteo se pueden usar para cosas como esta. Pueden ser muy eficientes. Crea la tabla de conteo a continuación. Creé la tabla de conteo con solo 24 filas para su ejemplo, pero puede crearla con la cantidad que desee para otros fines.
Supuse que su tabla se llamaba dbo.tblEvents, ejecute la consulta a continuación. Creo que esto es lo que estás buscando:
Creo que el crédito va a los siguientes enlaces, creo que aquí es donde me encontré con esto por primera vez:
http://www.sqlservercentral.com/articles/T-SQL/62867/
http://www.sqlservercentral.com/articles/T-SQL/74118/
fuente
Primero, mis disculpas por el retraso en mi respuesta desde mis últimos comentarios.
El tema surgió en los comentarios de que el uso de un CTE recursivo (rCTE de aquí en adelante) se ejecuta lo suficientemente rápido debido al bajo número de filas. Si bien puede parecer así, nada podría estar más lejos de la verdad.
CONSTRUYE TALLY TABLE Y TALLY FUNCTION
Antes de comenzar a probar, necesitamos construir una tabla de conteo física con el índice agrupado apropiado y una función de conteo estilo Itzik Ben-Gan. También haremos todo esto en TempDB para no dejar caer accidentalmente las golosinas de nadie.
Aquí está el código para construir la tabla de conteo y mi versión de producción actual del maravilloso código de Itzik.
Por cierto ... observe que construyó una tabla de conteo de un millón y una fila y le agregó un índice agrupado en aproximadamente un segundo más o menos. ¡Intente ESO con un rCTE y vea cuánto tarda! ;-)
CONSTRUIR ALGUNOS DATOS DE PRUEBA
También necesitamos algunos datos de prueba. Sí, estoy de acuerdo en que todas las funciones que vamos a probar, incluido el rCTE, se ejecutan en un milisegundo o menos durante solo 12 filas, pero esa es la trampa en la que muchas personas caen. Hablaremos más sobre esa trampa más tarde, pero, por ahora, simulemos llamar a cada función 40,000 veces, que es aproximadamente cuántas veces se llaman ciertas funciones en mi tienda en un día de 8 horas. Imagínense cuántas veces se podrían llamar tales funciones en un gran negocio minorista en línea.
Entonces, aquí está el código para construir 40,000 filas con fechas aleatorias, cada una con un Número de fila solo para fines de seguimiento. No me tomé el tiempo para hacer las horas enteras porque no importa aquí.
CONSTRUYA ALGUNAS FUNCIONES PARA HACER LA COSA DE 12 HORAS DE FILA
A continuación, convertí el código rCTE en una función y creé otras 3 funciones. Todos han sido creados como iTVF de alto rendimiento (funciones de valor de tabla en línea). Siempre se puede saber porque los iTVF nunca tienen un COMIENZO en ellos como Scalar o mTVF (funciones con valores de tabla de múltiples declaraciones).
Aquí está el código para construir esas 4 funciones ... Las nombré por el método que usan y no por lo que hacen solo para que sea más fácil identificarlas.
CONSTRUIR EL ARNÉS DE PRUEBA PARA PROBAR LAS FUNCIONES
Por último, pero no menos importante, necesitamos un arnés de prueba. Hago una verificación de línea de base y luego pruebo cada función de manera idéntica.
Aquí está el código para el arnés de prueba ...
Una cosa a tener en cuenta en el arnés de prueba anterior es que desvío toda la salida a variables "desechables". Eso es para tratar de mantener las mediciones de rendimiento tan puras como sea posible sin ninguna salida al disco o resultados de inclinación de la pantalla.
UNA PALABRA DE PRECAUCIÓN SOBRE LAS ESTADÍSTICAS FIJAS
Además, una advertencia para los posibles evaluadores ... NO DEBE usar SET STATISTICS cuando pruebe las funciones Scalar o mTVF. Solo se puede usar de forma segura en funciones iTVF como las de esta prueba. Se ha demostrado que SET STATISTICS hace que las funciones SCALAR se ejecuten cientos de veces más lento de lo que realmente lo hacen sin él. Sí, estoy tratando de inclinar otro molino de viento, pero eso sería una publicación más larga y no tengo tiempo para eso. Tengo un artículo en SQLServerCentral.com que habla sobre eso, pero no tiene sentido publicar el enlace aquí porque alguien se volverá loco al respecto.
LOS RESULTADOS DE LA PRUEBA
Entonces, aquí están los resultados de la prueba cuando ejecuto el arnés de prueba en mi pequeña computadora portátil i5 con 6GB de RAM.
El "SELECCIÓN DE BASE", que solo selecciona datos (cada fila creada 12 veces para simular el mismo volumen de retorno), llegó a la derecha aproximadamente 1/5 de segundo. Todo lo demás llegó aproximadamente a un cuarto de segundo. Bueno, todo excepto esa maldita función rCTE. Tomó 4 y 1/4 segundos o 16 veces más (1,600% más lento).
Y mire las lecturas lógicas (memoria IO) ... El rCTE consumió la friolera de 2,960,000 (casi 3 MILLONES de lecturas) mientras que las otras funciones solo consumieron aproximadamente 82,100. Eso significa que el rCTE consumió más de 34.3 veces más memoria IO que cualquiera de las otras funciones.
PENSAMIENTOS DE CIERRE
Resumamos El método rCTE para hacer esta cosa "pequeña" de 12 filas usó 16 VECES (1,600%) más CPU (y duración) y 34,3 VECES (3,430%) más memoria IO que cualquiera de las otras funciones.
Je ... Sé lo que estás pensando. "¡Gran cosa! Es solo una función".
Sí, de acuerdo, pero ¿cuántas otras funciones tienes? ¿Cuántos otros lugares fuera de las funciones tiene? ¿Y tiene alguno de esos que funcionan con más de 12 filas cada ejecución? Y, ¿hay alguna posibilidad de que alguien en una sacudida por un método pueda copiar ese código rCTE para algo mucho más grande?
Ok, es hora de ser franco. No tiene ningún sentido que las personas justifiquen el código de rendimiento desafiado solo por el supuesto recuento o uso de filas limitadas. Excepto cuando compra una caja MPP por quizás millones de dólares (sin mencionar el costo de reescribir el código para que funcione en una máquina de este tipo), no puede comprar una máquina que ejecute su código 16 veces más rápido (SSD ganó tampoco lo hagas ... todo esto estaba en la memoria de alta velocidad cuando lo probamos). El rendimiento está en el código. El buen rendimiento está en buen código.
¿Te imaginas si todo tu código se ejecutó "solo" 16 veces más rápido?
Nunca justifique código malo o de rendimiento desafiado en recuentos bajos o incluso bajo uso. Si lo hace, es posible que tenga que pedir prestado uno de los molinos de viento que me acusaron de inclinar para mantener sus CPU y discos lo suficientemente frescos. ;-)
UNA PALABRA EN LA PALABRA "TALLY"
Si estoy de acuerdo. Hablando semánticamente, la tabla de conteo contiene números, no "recuentos". En mi artículo original sobre el tema (no era el artículo original sobre la técnica, pero fue el primero), lo llamé "Tally" no por lo que contiene, sino por lo que hace ... es solía "contar" en lugar de repetir y "contar" algo es "contar" algo. ;-) Llámalo como quieras ... Tabla de números, Tabla de conteo, Tabla de secuencia, lo que sea. No me importa Para mí, "Tally" tiene más significado completo y, al ser un buen DBA perezoso, contiene solo 5 letras (2 son idénticas) en lugar de 7 y es más fácil de decir para la mayoría de las personas. También es "singular", que sigue mi convención de nomenclatura para tablas. ;-) Eso' También se llama el artículo que contenía una página de un libro de los años 60. Siempre me referiré a ella como una "Tabla de conteo" y aún sabrá lo que yo u otra persona queremos decir. También evito la notación húngara como la peste, pero llamé a la función "fnTally" para poder decir "Bueno, si usaras la función de conteo ef-en que te mostré, no tendrías un problema de rendimiento" sin que realmente sea Violación de recursos humanos. ;-) sin que en realidad sea una violación de recursos humanos. ;-) sin que en realidad sea una violación de recursos humanos. ;-)
Lo que más me preocupa es que las personas aprendan a usarlo correctamente en lugar de recurrir a cosas como los rCTE con problemas de rendimiento y otras formas de RBAR oculto.
fuente
Necesitará
RIGHT JOIN
sus datos con una consulta que devuelva un registro por cada hora que necesite.Vea esto para ver un par de formas de obtener números de fila que luego podría restar como horas de la hora actual.
En Oracle, una consulta jerárquica en dual generará filas:
fuente