J'ai posé une question ici: /programming/43807566/how-to-divide-two-values-from-the-same-column-but-at-different-rows
sur la division des valeurs de la même table, dans la même colonne mais sur des lignes différentes. Maintenant, j'ai le problème où j'ai plus de numérateurs et de dénominateurs (avec différents uns
). Est-ce toujours le self join
bon moyen de résoudre ce problème avec Postgres ou existe-t-il de meilleures solutions?
Exemple:
| postcode | value | uns |
|----------|-------|-----|
| AA | 40 | 53 |
| BB | 20 | 53 |
| AA | 10 | 54 |
| AA | 20 | 55 |
| AA | 10 | 56 |
| AA | 30 | 57 |
| AA | 50 | 58 |
| BB | 10 | 54 |
| BB | 10 | 55 |
| BB | 70 | 56 |
| BB | 80 | 57 |
| BB | 10 | 58 |
Le résultat devrait être:
| postcode | formula |
|----------|------------|
| AA | 18.888... |
| BB | 14.375 |
Où les valeurs sont regroupées par code postal et la formule est (valeur avec uns):
(V53 * V56 + V54 * V57 + V55 * V58) / (V56 + V57 + V58)
Faire attention à éviter une éventuelle division par zéro. La formule peut être encore plus complexe mais c'est un bon exemple.
postgresql
pivot
computed-column
Randomiser
la source
la source
uns
noms de colonnes deviennent - à partir de là, quelle que soit la formule qui utilise les valeurs, elle devrait pouvoir fonctionner. La formule sera-t-elle codée en dur ou dérivée dynamiquement d'une manière ou d'une autre?Réponses:
Il s'agit d'un problème de pivot / tableau croisé à la base, comme Michael a déjà été diagnostiqué avec précision.
Si vous n'êtes pas familier avec le
tablefunc
module dans Postgres, lisez les instructions de base ici:La requête devient simple et très rapide (plus rapide que les autres solutions présentées ici):
NULLIF
pour empêcher la division par zéro.dbfiddle ici
la source
Vous pouvez agréger toutes les paires uns / value dans un objet JSON, puis l'utiliser pour accéder aux valeurs UNS par leur nom. Cela nécessite une conversion car les valeurs ne peuvent être extraites que sous forme de texte à partir de l'objet JSON, mais la formule ressemble alors beaucoup à votre description:
J'ai divisé l'agrégation, l'évaluation du dénominateur et du diviseur et la division finale en trois étapes pour le rendre plus lisible.
Exemple en ligne: http://rextester.com/IZYT54566
Vous pouvez simplifier la formule en créant une fonction:
la source
Le modèle PIVOT fonctionnerait pour cela. Il convertit les valeurs des lignes en colonnes sur une seule ligne, selon leur clé commune. Il existe plusieurs façons de mettre cela en œuvre. Certains ne nécessitent qu'une seule analyse de table.
Après le PIVOT, vous auriez un tableau avec une ligne par code postal et une colonne par valeur. Le reste de la requête serait écrit comme s'il faisait référence à une seule table.
la source
En supposant qu'il
(postcode, uns)
s'agitUNIQUE
(probablement d'un PK), le modèle PIVOT, comme déjà commenté par @ michael-green, peut être implémenté de manière portable à l'aide de la requête suivante:Vérifiez-le sur SQLFiddle .
la source
En supposant qu'il
(postcode, uns)
s'agitUNIQUE
(probablement d'un PK), probablement de la manière la plus simple, probablement la plus portable, bien que probablement pas optimale: utilisez autant de sous-sélections que nécessaire :Vérifiez à SQLFiddle .
la source