Глядя, чтобы рассчитать наиболее подходящую единицу измерения для списка веществ, где вещества приведены в разных (но совместимых) единичных объемах.
Таблица перевода единиц
Таблица преобразования единиц хранит различные единицы и их взаимосвязь:
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
Сортировка по коэффициенту показывает, что parent_id
связывает дочернюю единицу с ее числовым улучшением.
Эта таблица может быть создана в PostgreSQL с помощью:
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)
)
Должен быть внешний ключ от parent_id
до id
.
Таблица веществ
В таблице веществ указаны конкретные количества веществ. Например:
id unit label quantity
1 "microlitre" mercury 5
2 "millilitre" water 500
3 "centilitre" water 2
4 "microlitre" mercury 10
5 "millilitre" water 600
Таблица может напоминать:
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)
)
проблема
Как бы вы создали запрос, который находит измерение для представления суммы веществ, используя наименьшее количество цифр, которые имеют целое число (и, возможно, вещественный компонент)?
Например, как бы вы вернулись:
quantity unit label
15 microlitre mercury
112 centilitre water
Но нет:
quantity unit label
15 microlitre mercury
1.12 litre water
Потому что 112 имеет меньше реальных цифр, чем 1,12, а 112 меньше 1120. Тем не менее, в определенных ситуациях использование реальных цифр короче - например, 1,1 литра против 110 сантилитров.
В основном у меня проблемы с выбором правильной единицы на основе рекурсивного отношения.
Исходный код
Пока что у меня (очевидно, не работает):
-- Normalize the quantities
select
sum( coefficient * quantity ) AS kilolitres
from
unit_conversion uc,
substance s
where
uc.unit = s.unit
group by
s.label
идеи
Требуется ли для этого использование журнала 10 для определения количества цифр?
Ограничения
Единицы не все в полномочиях десяти. Например: http://unitsofmeasure.org/ucum-essence.xml
источник
Ответы:
Это выглядит некрасиво:
но похоже делает свое дело:
На самом деле вам не нужны родительско-дочерние отношения в
unit_conversion
таблице, потому что единицы в одной семье естественно связаны друг с другом по порядкуcoefficient
, пока вы определили семью.источник
Я думаю, это можно в значительной степени упростить.
1. Изменить
unit_conversion
таблицуИли, если вы не можете изменить таблицу, просто добавьте столбец
exp10
для «экспоненты 10», который совпадает с количеством цифр для сдвига в десятичной системе:2. Написать функцию
чтобы рассчитать количество позиций для смещения влево или вправо:
3. Запрос
Объясните:
f_shift_comma()
сверху.DISTINCT ON ()
иORDER BY
.COALESCE()
.-> Демоверсия SQLfiddle .
источник