2010-02-07 4 views
0

Possible en double:
Function to Calculate Median in Sql Serverfonction SQL pour calculer la médiane

J'ai une table contenant deux champs (plus, mais pas pertinent). Les champs sont Prix et Quantité. Je veux trouver plusieurs données statistiques pour ce tableau, parmi lesquelles le prix médian ajusté à la quantité.

Aujourd'hui, j'ai une fonction de base-lent-pas très beau en place qui prend la quantité totale et diviser par 2. Ensuite, je marche les enregistrements classés par prix et soustrayant la quantité de la quantité totale. Lorsque la quantité totale a atteint 0, j'ai ma médiane.

Comme vous pouvez le deviner, c'est lent ... très lent. Je suis à la recherche d'idées pour rendre le tout meilleur, plus rapide et plus «super-duper».

J'utilise MS SQL Express 2008 ...

+0

On m'a demandé plusieurs fois avant http: // stackoverflow.com/questions/1342898/function-to-calculate-median-in-sql-server – gbn

+0

N'est-ce pas une seule colonne? Je ne peux pas comprendre comment cela se rapporte à mon problème de deux colonnes. – rozon

Répondre

0

Cela devrait au moins le faire avec seulement deux requêtes au lieu d'une boucle:

declare @total int 

select @total = sum(Quantity) from Products 

select top 1 p.Price 
from Products p 
order by abs((select sum(Quantity) from Products where Price < p.Price) - (@total/2)) 

Un indice sur le prix avec la quantité que sur le terrain inclus serait probablement à des merveilles pour la performance ...

0

Je ne suis pas près de ma boîte SQL pour fouiller dans les trucs OVER PARTITION, mais en tirer parti devrait faire ce que vous cherchez. Consultez la section SQL 2005 de cet article pour des exemples: link text

0

Ceci est probablement le meilleur que je l'ai utilisé dans le passé sans l'aide de vues:

SELECT AVG(DISTINCT Quantity) 
    FROM (SELECT F1.ID, F1.Quantity, 
     SUM(CASE WHEN F2.Quantity < F1.Quantity THEN 1 ELSE 0 END), 
     SUM(CASE WHEN F2.Quantity = F1.Quantity THEN 1 ELSE 0 END), 
     SUM(CASE WHEN F2.Quantity > F1.Quantity THEN 1 ELSE 0 END) 
     FROM [Table] as F1, [Table] as F2 
     GROUP BY F1.ID, F1.Quantity) AS Partitions (ID, Quantity, Lesser, Equal, Greater) 
    WHERE Lesser = Greater 
    OR (Lesser <= (SELECT COUNT(*) FROM [Table])/2.0 AND Greater <= (SELECT COUNT(*) FROM [Table])/2.0); 
Questions connexes