Saltar al contenido

¿Cuál es la forma más eficiente de obtener el mínimo de varias columnas en SQL Server 2005?

Estate atento ya que en esta sección encontrarás el resultado que buscas.

Solución:

Probé el rendimiento de los 3 métodos y esto es lo que encontré:

  • 1 registro: sin diferencia notable
  • 10 registros: ninguna diferencia notable
  • 1000 registros: ninguna diferencia notable
  • 10.000 registros: UNION la subconsulta fue un poco más lenta. Él CASE WHEN la consulta es un poco más rápida que la UNPIVOT uno.
  • 100.000 registros: UNION la subconsulta es significativamente más lenta, pero UNPIVOT la consulta se vuelve un poco más rápida que la CASE WHEN consulta
  • 500.000 registros: UNION la subconsulta sigue siendo significativamente más lenta, pero UNPIVOT se vuelve mucho más rápido que el CASE WHEN consulta

Así que los resultados finales parecen ser

  • Con conjuntos de registros más pequeños, no parece haber una diferencia suficiente como para importar. Use lo que sea más fácil de leer y mantener.

  • Una vez que comience a entrar en conjuntos de registros más grandes, el UNION ALL la subconsulta comienza a funcionar mal en comparación con los otros dos métodos.

  • Él CASE declaración funciona mejor hasta cierto punto (en mi caso, alrededor de 100k filas), y qué punto el UNPIVOT la consulta se convierte en la consulta de mejor rendimiento

El número real en el que una consulta se vuelve mejor que otra probablemente cambiará como resultado de su hardware, esquema de base de datos, datos y carga actual del servidor, así que asegúrese de probar con su propio sistema si le preocupa el rendimiento.

También realicé algunas pruebas usando la respuesta de Mikael; sin embargo, fue más lento que los otros 3 métodos probados aquí para la mayoría de los tamaños de conjuntos de registros. La única excepción fue que lo hizo mejor que el UNION ALL consulta de tamaños de conjuntos de registros muy grandes. Sin embargo, me gusta el hecho de que muestra el nombre de la columna además del valor más pequeño.

No soy un dba, por lo que es posible que no haya optimizado mis pruebas y me haya perdido algo. Estaba probando con los datos reales en vivo, por lo que eso puede haber afectado los resultados. Traté de dar cuenta de eso ejecutando cada consulta varias veces, pero nunca se sabe. Definitivamente estaría interesado si alguien escribiera una prueba limpia de esto y compartiera sus resultados.

No sé qué es lo más rápido, pero podrías intentar algo como esto.

declare @T table
(
  Col1 int,
  Col2 int,
  Col3 int,
  Col4 int,
  Col5 int,
  Col6 int
)

insert into @T values(1, 2, 3, 4, 5, 6)
insert into @T values(2, 3, 1, 4, 5, 6)

select T4.ColName, T4.ColValue
from @T as T1
  cross apply (
                select T3.ColValue, T3.ColName
                from (
                       select row_number() over(order by T2.ColValue) as rn,
                              T2.ColValue,
                              T2.ColName
                       from (
                              select T1.Col1, 'Col1' union all
                              select T1.Col2, 'Col2' union all
                              select T1.Col3, 'Col3' union all
                              select T1.Col4, 'Col4' union all
                              select T1.Col5, 'Col5' union all
                              select T1.Col6, 'Col6'
                            ) as T2(ColValue, ColName)
                     ) as T3
                where T3.rn = 1
              ) as T4

Resultado:

ColName ColValue
------- -----------
Col1    1
Col3    1

Si no está interesado en qué columna tiene el valor mínimo, puede usar esto en su lugar.

declare @T table
(
  Id int,
  Col1 int,
  Col2 int,
  Col3 int,
  Col4 int,
  Col5 int,
  Col6 int
)

insert into @T
select 1,        3,       4,       0,       2,       1,       5 union all
select 2,        2,       6,      10,       5,       7,       9 union all
select 3,        1,       1,       2,       3,       4,       5 union all
select 4,        9,       5,       4,       6,       8,       9

select T.Id, (select min(T1.ColValue)
              from (
                      select T.Col1 union all
                      select T.Col2 union all
                      select T.Col3 union all
                      select T.Col4 union all
                      select T.Col5 union all
                      select T.Col6
                    ) as T1(ColValue)
             ) as ColValue
from @T as T

Una consulta no dinámica simplificada.

select Id, min(ColValue) as ColValue
from @T
unpivot (ColValue for Col in (Col1, Col2, Col3, Col4, Col5, Col6)) as U
group by Id

Agregue una columna calculada persistente que use un CASE declaración para hacer la lógica que necesita.

El valor mínimo siempre estará disponible de manera eficiente cuando necesite hacer una unión (o cualquier otra cosa) basada en ese valor.

El valor se volverá a calcular cada vez que cambie cualquiera de los valores de origen (INSERT/UPDATE/MERGE). No digo que esta sea necesariamente la mejor solución para la carga de trabajo, simplemente la ofrezco como un solución, al igual que las otras respuestas. Solo el OP puede determinar cuál es mejor para la carga de trabajo.

Si estás de acuerdo, eres capaz de dejar un tutorial acerca de qué te ha impresionado de este ensayo.

¡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 *