It has been a couple of years since this question was asked, but I created a solution that may be of interest for this topic in the future. The following solution is tested on 2012 SQL Server. To reduce the size of the code on the page, I provide only bulk measurements.
CREATE TABLE [Measurement type] ( [Type ID] INT IDENTITY(1,1) PRIMARY KEY NOT NULL, [Type Name] NVARCHAR(30) NOT NULL ) GO CREATE TABLE [Measurement unit] ( [Unit ID] INT IDENTITY(1,1) PRIMARY KEY NOT NULL, [Type ID] INT REFERENCES [Measurement type]([Type ID]) NOT NULL, [Unit name] NVARCHAR(30) NOT NULL, [Unit symbol] NVARCHAR(10) NOT NULL ) GO /* Use both multiplicand and dividend to reduce rounding errors */ CREATE TABLE [Measurement conversions] ( [Type ID] INT NOT NULL REFERENCES [Measurement type]([Type ID]), [From Unit ID] INT NOT NULL REFERENCES [Measurement unit]([Unit ID]), [To Unit ID] INT NOT NULL REFERENCES [Measurement unit]([Unit ID]), [From Unit Offset] FLOAT NOT NULL DEFAULT(0), [Multiplicand] FLOAT NOT NULL DEFAULT(1), [Dividend] FLOAT NOT NULL DEFAULT(1), [To Unit Offset] FLOAT NOT NULL DEFAULT(0), PRIMARY KEY ([Type ID], [From Unit ID], [To Unit ID]) ) GO SET IDENTITY_INSERT [Measurement type] ON GO INSERT INTO [Measurement type]([Type ID], [Type Name]) VALUES (1, 'Length'), (2, 'Area'), (3, 'Volume'), (4, 'Mass'), (5, 'Temperature') -- ... GO SET IDENTITY_INSERT [Measurement type] OFF GO GO SET IDENTITY_INSERT [Measurement unit] ON GO INSERT INTO [Measurement unit]([Unit ID], [Type ID], [Unit name], [Unit symbol]) VALUES (28, 4, 'Milligram', 'mg'), (29, 4, 'Gram', 'g'), (30, 4, 'Kilogram', 'kg'), (31, 4, 'Tonne', 't'), (32, 4, 'Ounce', 'oz'), (33, 4, 'Pound', 'lb'), (34, 4, 'Stone', 's'), (35, 4, 'hundred weight', 'cwt'), (36, 4, 'UK long ton', 'ton') GO SET IDENTITY_INSERT [Measurement unit] ON GO INSERT INTO [Measurement conversions]([Type ID], [From Unit ID], [To Unit ID], [Multiplicand], [Dividend]) VALUES (4, 28, 29, 1, 1000), (4, 28, 30, 1, 1000000), (4, 28, 31, 1, 1000000000), (4, 28, 32, 1, 28350), (4, 32, 33, 1, 16), (4, 32, 34, 1, 224), (4, 32, 35, 1, 50802345), (4, 32, 36, 1, 35840) GO INSERT INTO [Measurement conversions]([Type ID], [From Unit ID], [To Unit ID], [From Unit Offset], [Multiplicand], [Dividend], [To Unit Offset]) SELECT DISTINCT [Measurement Conversions].[Type ID], [Measurement Conversions].[To Unit ID], [Measurement Conversions].[From Unit ID], -[Measurement Conversions].[To Unit Offset], [Measurement Conversions].[Dividend], [Measurement Conversions].[Multiplicand], -[Measurement Conversions].[From Unit Offset] FROM [Measurement Conversions] -- LEFT JOIN Used to reduce errors on inserting same key twice. LEFT JOIN [Measurement conversions] AS [Existing] ON [Measurement Conversions].[From Unit ID] = [Existing].[To Unit ID] AND [Measurement Conversions].[To Unit ID] = [Existing].[From Unit ID] WHERE [Existing].[Type ID] IS NULL GO
Then run the following query until it turns to the zero rows, it can complain about the multiple Equal ID if there are several paths leading to different conversion rates between the same values.
INSERT INTO [Measurement conversions]([Type ID], [From Unit ID], [To Unit ID], [From Unit Offset], [Multiplicand], [Dividend], [To Unit Offset]) SELECT DISTINCT [From].[Type ID], [From].[To Unit ID] AS [From Unit ID], [To].[To Unit ID], -[From].[To Unit Offset] + (([To].[From Unit Offset]) * [From].[Multiplicand] / [From].Dividend) AS [From Unit Offset], [From].[Dividend] * [To].[Multiplicand] AS Multiplicand, [From].[Multiplicand] * [To].[Dividend] AS Dividend, [To].[To Unit Offset] - (([From].[From Unit Offset]) * [To].[Multiplicand] / [To].Dividend) AS [To Unit Offset] FROM [Measurement conversions] AS [From] CROSS JOIN [Measurement conversions] AS [To]
Finally, to remove the factors and dividers that directly cancel each other out:
UPDATE [Measurement conversions] SET [Multiplicand] = 1, [Dividend] = 1 WHERE Multiplicand = Dividend