Esta es una pregunta de eficiencia de SQL.Subconsultas de SQL: ¿hay una manera mejor?
Hace un tiempo tuve que escribir una colección de consultas para extraer datos de un sistema ERP. La mayoría de estos fueron bastante simples, pero uno de ellos resultó en una consulta bastante ineficiente y me ha molestado desde entonces, ya que tiene que haber una mejor manera.
El problema no es complejo. Tienes filas de datos de ventas. En cada fila tiene cantidad, precio de venta y el código del vendedor, entre otra información.
La comisión se paga según una escala progresiva escalonada. Cuanto más vendan, mejor será la comisión. Los pasos pueden ser 1000, 10000, 10000 $, etc. El problema del mundo real es más complejo, pero eso es esencialmente así.
La única manera que he encontrado para hacer esto era para hacer algo como esto (obviamente no es el verdadero consulta)
select qty, price, salesman,
(select top 1 percentage from comissions
where comisiones.salesman = saleslines.salesman
and saleslines.qty > comisiones.qty
order by comissiones.qty desc
) percentage
from saleslines
esto da lugar a la comisión correcta, pero es terriblemente pesado.
¿Hay una mejor manera de hacerlo? No estoy buscando a alguien para reescribir mi sql, más 'eche un vistazo como consultas foobar' y puedo tomarlo desde allí.
La estructura de comisiones de la vida real se puede especificar para diferentes vendedores, artículos y clientes, e incluso para fechas de venta. También cambia de vez en cuando, por lo que todo tiene que ser impulsado por los datos en las tablas ... es decir, no puedo poner rangos fijos en el sql. La consulta actual devuelve unas 3-400000 filas y tarda alrededor de 20-30 segundos. Afortunadamente, solo se usa mensualmente pero la lentitud me molesta un poco.
Esto está en mssql.
Ian
edición:
que debería haber dado un ejemplo más complejo desde el principio. Ahora me doy cuenta de que a mi ejemplo inicial le faltan algunos elementos esenciales de la complejidad, disculpas a todos.
Esto puede captar mejor que
select client-code, product, product-family, qty, price, discount, salesman,
(select top 1 percentage from comissions
where comisiones.salesman = saleslines.salesman
and saleslines.qty > comisiones.qty
and [
a collection of conditions which may or may not apply:
Exclude rows if the salesman has offered discounts above max discounts
which appear in each row in the commissions table
There may be a special scale for the product family
There may be a special scale for the product
There may be a special scale for the client
A few more cases
]
order by [
The user can control the order though a table
which can prioritize by client, family or product
It normally goes from most to least specific.
]
) percentage
from saleslines
no hace falta decir la consulta real no es fácil de seguir. Solo para hacer la vida más interesante, su denominación es multilingüe.
Por lo tanto, para cada fila de línea de venta, la comisión puede ser diferente.
Puede parecer demasiado complejo, pero si piensas en cómo pagarías una comisión, tiene sentido. No quiere pagar a alguien por vender cosas con grandes descuentos, también quiere poder ofrecer a un cliente en particular un descuento en un producto en particular si compra unidades X. El vendedor debería ganar más si vende más.
En todo lo anterior, excluyo las ofertas especiales con fecha limitada.
Creo que las particiones pueden ser la solución, pero necesito explorar esto más a fondo, ya que no sé nada sobre las particiones. Me ha dado algunas ideas.
si su única carrera mensual, yo no me preocuparía por eso. Parece que tiene que hacer muchos cálculos en varias tablas grandes. Si tuviera que ejecutarse con más frecuencia, es posible que desee construir el conjunto de resultados de forma incremental utilizando una estrategia diferente. –
A veces es mejor medir realmente el trabajo e introducir una mejor infraestructura, como índices o discos más rápidos, etc. Debe perfilar la consulta y ver que los bits sean pesados. –
¿Qué versión de SQL Server estás usando? –