Suchen Sie nach der am besten geeigneten Maßeinheit für eine Liste von Stoffen, bei denen die Stoffe in unterschiedlichen (aber kompatiblen) Volumeneinheiten angegeben sind.
Einheitenumrechnungstabelle
In der Einheitenumrechnungstabelle werden verschiedene Einheiten gespeichert und wie sich diese Einheiten verhalten:
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
Das Sortieren nach dem Koeffizienten zeigt, dass parent_id
eine untergeordnete Einheit mit ihrem numerischen Vorgesetzten verknüpft ist.
Diese Tabelle kann in PostgreSQL erstellt werden mit:
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)
)
Es sollte einen Fremdschlüssel von parent_id
bis geben id
.
Substanztabelle
In der Stofftabelle sind bestimmte Stoffmengen aufgeführt. Beispielsweise:
id unit label quantity
1 "microlitre" mercury 5
2 "millilitre" water 500
3 "centilitre" water 2
4 "microlitre" mercury 10
5 "millilitre" water 600
Die Tabelle könnte ähneln:
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)
)
Problem
Wie würden Sie eine Abfrage erstellen, die eine Messung findet, um die Summe der Substanzen mit den wenigsten Ziffern darzustellen, die eine ganze Zahl (und optional eine reale Komponente) haben?
Wie würden Sie zum Beispiel zurückkehren:
quantity unit label
15 microlitre mercury
112 centilitre water
Aber nicht:
quantity unit label
15 microlitre mercury
1.12 litre water
Weil 112 weniger reelle Ziffern als 1,12 hat und 112 kleiner als 1120 ist. In bestimmten Situationen ist die Verwendung reeller Ziffern jedoch kürzer - beispielsweise 1,1 Liter gegenüber 110 Zentilitern.
Meistens habe ich Probleme, die richtige Einheit basierend auf der rekursiven Beziehung auszuwählen.
Quellcode
Bisher habe ich (offensichtlich nicht arbeitend):
-- Normalize the quantities
select
sum( coefficient * quantity ) AS kilolitres
from
unit_conversion uc,
substance s
where
uc.unit = s.unit
group by
s.label
Ideen
Erfordert dies die Verwendung von Protokoll 10 , um die Anzahl der Ziffern zu bestimmen?
Einschränkungen
Die Einheiten sind nicht alle in Zehnerpotenzen. Zum Beispiel: http://unitsofmeasure.org/ucum-essence.xml
quelle
Antworten:
Das sieht hässlich aus:
aber scheint den Trick zu tun:
Sie brauchen die Eltern-Kind-Beziehung in der
unit_conversion
Tabelle nicht wirklich , da die Einheiten in derselben Familie natürlich in der Reihenfolge von miteinander verwandt sindcoefficient
, solange Sie die Familie identifiziert haben.quelle
Ich denke, das kann weitgehend vereinfacht werden.
1. Ändern Sie die
unit_conversion
TabelleWenn Sie die Tabelle nicht ändern können, fügen Sie einfach die Spalte
exp10
für "Exponentenbasis 10" hinzu, die mit der Anzahl der im Dezimalsystem zu verschiebenden Stellen übereinstimmt:2. Schreibfunktion
um die Anzahl der Positionen zu berechnen, die nach links oder rechts verschoben werden sollen:
3. Abfrage
Erklären:
f_shift_comma()
von oben verschoben werden sollen .DISTINCT ON ()
undORDER BY
.COALESCE()
.-> SQLfiddle- Demo.
quelle