Mencari untuk menghitung unit pengukuran yang paling cocok untuk daftar zat di mana zat diberikan dalam volume satuan yang berbeda (tetapi kompatibel).
Tabel Konversi Satuan
Tabel konversi unit menyimpan berbagai unit dan bagaimana unit tersebut berhubungan:
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
Penyortiran berdasarkan koefisien menunjukkan bahwa parent_id
tautan unit anak ke atasan numeriknya.
Tabel ini dapat dibuat di PostgreSQL menggunakan:
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)
)
Harus ada kunci asing dari parent_id
ke id
.
Tabel zat
Tabel Substansi mencantumkan jumlah zat tertentu. Sebagai contoh:
id unit label quantity
1 "microlitre" mercury 5
2 "millilitre" water 500
3 "centilitre" water 2
4 "microlitre" mercury 10
5 "millilitre" water 600
Tabelnya mungkin menyerupai:
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)
)
Masalah
Bagaimana Anda membuat kueri yang menemukan pengukuran untuk mewakili jumlah zat menggunakan digit paling sedikit yang memiliki bilangan bulat (dan komponen nyata opsional)?
Misalnya, bagaimana Anda akan kembali:
quantity unit label
15 microlitre mercury
112 centilitre water
Tapi tidak:
quantity unit label
15 microlitre mercury
1.12 litre water
Karena 112 memiliki digit nyata lebih sedikit dari 1,12 dan 112 lebih kecil dari 1120. Namun dalam situasi tertentu menggunakan digit nyata lebih pendek - seperti 1,1 liter vs 110 centilitre.
Sebagian besar, saya mengalami masalah dalam memilih unit yang benar berdasarkan pada hubungan rekursif.
Kode sumber
Sejauh ini saya punya (jelas tidak bekerja):
-- Normalize the quantities
select
sum( coefficient * quantity ) AS kilolitres
from
unit_conversion uc,
substance s
where
uc.unit = s.unit
group by
s.label
Ide ide
Apakah ini mengharuskan menggunakan log 10 untuk menentukan jumlah digit?
Kendala
Unit tidak semuanya memiliki kekuatan sepuluh. Misalnya: http://unitsofmeasure.org/ucum-essence.xml
sumber
Jawaban:
Ini terlihat jelek:
tetapi tampaknya melakukan trik:
Anda tidak benar-benar membutuhkan hubungan orang tua-anak dalam
unit_conversion
tabel, karena unit-unit dalam keluarga yang sama secara alami terkait satu sama lain berdasarkan urutancoefficient
, selama Anda memiliki keluarga yang diidentifikasi.sumber
Saya pikir, ini bisa disederhanakan.
1. Ubah
unit_conversion
tabelAtau, jika Anda tidak dapat mengubah tabel, cukup tambahkan kolom
exp10
untuk "basis eksponen 10", yang bertepatan dengan jumlah digit untuk bergeser dalam sistem desimal:2. Fungsi menulis
untuk menghitung jumlah posisi untuk bergeser ke kiri atau kanan:
3. Pertanyaan
Menjelaskan:
f_shift_comma()
dari atas.DISTINCT ON ()
danORDER BY
.COALESCE()
.-> Demo SQLfiddle .
sumber