Vous cherchez à calculer l'unité de mesure la plus appropriée pour une liste de substances où les substances sont données dans des volumes unitaires différents (mais compatibles).
Tableau de conversion des unités
La table de conversion des unités stocke différentes unités et comment ces unités sont liées:
id unit coefficient parent_id
36 "microlitre" 0.0000000010000000000000000 37
37 "millilitre" 0.0000010000000000000000000 5
5 "centilitre" 0.0000100000000000000000000 18
18 "decilitre" 0.0001000000000000000000000 34
34 "litre" 0.0010000000000000000000000 19
19 "dekalitre" 0.0100000000000000000000000 29
29 "hectolitre" 0.1000000000000000000000000 33
33 "kilolitre" 1.0000000000000000000000000 35
35 "megalitre" 1000.0000000000000000000000 0
Le tri par coefficient montre que le parent_id
lien entre une unité enfant et son supérieur numérique.
Cette table peut être créée dans PostgreSQL en utilisant:
CREATE TABLE unit_conversion (
id serial NOT NULL, -- Primary key.
unit text NOT NULL, -- Unit of measurement name.
coefficient numeric(30,25) NOT NULL DEFAULT 0, -- Conversion value.
parent_id integer NOT NULL DEFAULT 0, -- Relates units in order of increasing measurement volume.
CONSTRAINT pk_unit_conversion PRIMARY KEY (id)
)
Il doit y avoir une clé étrangère de parent_id
à id
.
Tableau des substances
Le tableau des substances répertorie des quantités spécifiques de substances. Par exemple:
id unit label quantity
1 "microlitre" mercury 5
2 "millilitre" water 500
3 "centilitre" water 2
4 "microlitre" mercury 10
5 "millilitre" water 600
Le tableau pourrait ressembler à:
CREATE TABLE substance (
id bigserial NOT NULL, -- Uniquely identifies this row.
unit text NOT NULL, -- Foreign key to unit conversion.
label text NOT NULL, -- Name of the substance.
quantity numeric( 10, 4 ) NOT NULL, -- Amount of the substance.
CONSTRAINT pk_substance PRIMARY KEY (id)
)
Problème
Comment pourriez-vous créer une requête qui trouve une mesure pour représenter la somme des substances en utilisant le moins de chiffres qui a un nombre entier (et éventuellement une composante réelle)?
Par exemple, comment retourneriez-vous:
quantity unit label
15 microlitre mercury
112 centilitre water
Mais non:
quantity unit label
15 microlitre mercury
1.12 litre water
Parce que 112 a moins de chiffres réels que 1,12 et 112 est plus petit que 1120. Pourtant, dans certaines situations, l'utilisation de chiffres réels est plus courte - comme 1,1 litre contre 110 centilitres.
Surtout, j'ai du mal à choisir l'unité correcte en fonction de la relation récursive.
Code source
Jusqu'à présent, j'ai (évidemment ne fonctionne pas):
-- Normalize the quantities
select
sum( coefficient * quantity ) AS kilolitres
from
unit_conversion uc,
substance s
where
uc.unit = s.unit
group by
s.label
Des idées
Cela nécessite-t-il d'utiliser le journal 10 pour déterminer le nombre de chiffres?
Contraintes
Les unités ne sont pas toutes en puissance de dix. Par exemple: http://unitsofmeasure.org/ucum-essence.xml
la source
Réponses:
Cela a l'air moche:
mais semble faire l'affaire:
Vous n'avez pas vraiment besoin de la relation parent-enfant dans le
unit_conversion
tableau, car les unités d'une même famille sont naturellement liées les unes aux autres par ordre decoefficient
, tant que la famille est identifiée.la source
Je pense que cela peut être largement simplifié.
1. Modifier le
unit_conversion
tableauOu, si vous ne pouvez pas modifier le tableau, ajoutez simplement la colonne
exp10
"exposant base 10", qui coïncide avec le nombre de chiffres à décaler dans le système décimal:2. Fonction d'écriture
pour calculer le nombre de positions à décaler vers la gauche ou la droite:
3. Requête
Explique:
f_shift_comma()
d'en haut.DISTINCT ON ()
etORDER BY
.COALESCE()
.-> Démo SQLfiddle .
la source