2016-09-25 1 views
2

A partir de la requête PostgreSQLChoisir n premiers éléments de telle sorte que la somme accumulée atteigne une valeur donnée

SELECT filename FROM files_storage ORDER BY date; 

je voudrais réduire la table de sortie à la première n rangées de telle sorte que la somme accumulée à partir de la rangée 1 à n d'une colonne appelée size atteint au moins max_value.

Exemple:

date   filename size 
2016-09-01 /a/aaa/ 20 
2016-09-02 /a/bbb/ 70 
2016-09-03 /a/ccc/ 20 
2016-09-04 /a/ddd/ 30 
2016-09-05 /a/eee/ 50 

Si max_value est 100, je veux revenir les trois premières lignes parce que 20 + 70 + 20 >= 100.

J'ai vu des réponses à des questions similaires, mais rien dans PostgreSQL.

+0

Je note que vos données d'exemple n'ont pas 'date', mais votre requête le fait. –

Répondre

0

Utilisez la fonctionnalité de somme cumulative:

SELECT fs.* 
FROM (SELECT fs.*, SUM(size) OVER (ORDER BY date) as running_sum 
     FROM files_storage 
    ) fs 
WHERE running_sum >= 100 AND running_sum - size < 100; 

Oh, qui obtient la première ligne qui traverse la frontière.

Vous voulez tous, donc au lieu:

SELECT fs.* 
FROM (SELECT fs.*, SUM(size) OVER (ORDER BY date) as running_sum 
     FROM files_storage 
    ) fs 
WHERE running_sum - size < 100; 

Si vous pouvez avoir des dates en double et que vous souhaitez arbitrairement une valeur lorsque les valeurs en double à la même date pourrait demander:

SELECT fs.* 
FROM (SELECT fs.*, 
      SUM(size) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as running_sum 
     FROM files_storage 
    ) fs 
WHERE running_sum - size < 100; 
2

Voici mon prendre:

SELECT filename, size 
FROM (
    SELECT 
     filename, 
     size, 
     coalesce(sum(size) OVER (ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING),0) AS sum 
    FROM files_storage 
) t 
WHERE sum<100 

J'utilise sum en fonction de la fenêtre ici pour Càlcul mangé pour chaque fichier, la somme des tailles de tous les fichiers précédents (non compris l'actuel). Ensuite, je filtre les lignes selon que ce nombre est inférieur au seuil. Le fait d'avoir exclu le fichier actuel de la somme garantit que nous obtiendrons une ligne de plus, ce qui sera les fichiers qui feront basculer la somme sur le seuil.

+1

IMO question beaucoup plus intéressante: comment éviter le balayage de toute la table pour cela. – Abelisto

+0

@Abelisto Que vous avez besoin d'une colonne supplémentaire pour stocker les sommes partielles et un index sur la colonne. – redneb