2017-07-17 1 views
1

Voici un exemple du problème commercial.Sélectionner les lignes dont la somme est égale à 80% du total

J'ai 10 ventes qui ont abouti à une marge négative. Nous voulons examiner ces enregistrements, nous utilisons généralement la règle 20/80 dans les commentaires. Soit 20% des ventes représenteront probablement 80% de la marge négative.

Donc, avec les dossiers ci-dessous ....

+----+-------+ 
| ID | Value | 
+----+-------+ 
| 1 | 30 | 
| 2 | 30 | 
| 3 | 20 | 
| 4 | 10 | 
| 5 |  5 | 
| 6 |  5 | 
| 7 |  2 | 
| 8 |  2 | 
| 9 |  1 | 
| 10 |  1 | 
+----+-------+ 

Je veux revenir ...

+----+-------+ 
| ID | Value | 
+----+-------+ 
| 1 | 30 | 
| 2 | 30 | 
| 3 | 20 | 
| 4 | 10 | 
+----+-------+ 

Le total de la valeur est de 106, 80% est alors 84,8. J'ai besoin de tous les enregistrements, triés par ordre décroissant qui totalisent la valeur au moins 84.8

Nous utilisons Microsoft APS PDW SQL, mais peut traiter sur SMP si nécessaire.

+0

Copie possible de [Comment obtenir les valeurs de pourcentage 'n' supérieures] (https: // stacko verflow.com/questions/16666376/how-to-get-top-n-percentage-values) – JeffUK

Répondre

3

assumait ses fonctions de fenêtre sont pris en charge, vous pouvez utiliser

with cte as (select id,value 
      ,sum(value) over(order by value desc,id) as running_sum 
      ,sum(value) over() as total 
      from tbl 
      ) 
select id,value from cte where running_sum < total*0.8 
union all 
select top 1 id,value from cte where running_sum >= total*0.8 order by value desc 
+1

Bonne réponse. Je pense que cela devrait être ' = total * 0.8', cependant, pour le cas nous arrivons exactement à 80%. –

+0

@ThorstenKettner .. vous avez absolument raison. Je l'ai raté. édité la réponse maintenant, pour refléter votre suggestion. –

+0

C'était parfait, merci beaucoup. –

0

Une façon est d'utiliser les totaux en cours d'exécution:

select 
    id, 
    value 
from 
(
    select 
    id, 
    value, 
    sum(value) over() as total, 
    sum(value) over (order by value desc) as till_here, 
    sum(value) over (order by value desc rows between unbounded preceding and 1 preceding) 
     as till_prev 
    from mytable 
) summed_up 
where till_here * 1.0/total <= 0.8 
    or (till_here * 1.0/total >= 0.8 and coalesce(till_prev, 0) * 1.0/total < 0.8) 
order by value desc;