表表示是实际问题的简化,因为它可以捕获情况,但更易于理解。
两个表包含度量单位的定义。有一个包含所有单位符号的表和一个具有许多相关的表,其中包含所有单位的定义段。例如,
0.9144
米22
码220
码的弗龙1
链乘以1
弗隆的一英亩表格:
measurement_units
id name is_base_unit
----------------------------------
1 meter 1
2 yard 0
3 chain 0
4 furlong 0
5 acre 0
measurement_unit_derivations
id measurement_unit_id derives_from_measurement_unit_id factor
---------------------------------------------------------------------------
1 2 1 0.9144
2 3 2 22
3 4 2 220
4 5 3 1
5 5 4 1
我正在尝试编写一个递归公用表表达式,其中计算每个度量单位的比率相对于相关物理尺寸的基本单位。结果应该例如包含院子与米的比率和英亩与m ^ 2的比率。它应该看起来像这样:
measurement_unit_id name ratio
-------------------------------------------
1 meter 1
2 yard 0.9144
3 chain 20.1168
4 furlong 201.168
5 acre 4046.8564224
问题在于,一个单位可以衍生自其他多个单位。例如,为了找出一英亩与m ^ 2的比率,我们将看到它来自一条furlong和一条链,这些链又来自其他单位。
我无法继续:
WITH RECURSIVE cte AS (
SELECT
id AS measurement_unit_id
name,
1 AS ratio
FROM measurement_units
WHERE is_base_unit = 1
UNION ALL
???
)
编辑: 关于米和英亩的示例表很容易描述,但也太简单了。我创建了另一个示例,在该示例中递归查询也应该起作用:
measurement_units
id name is_base_unit
----------------------------------
1 A 1
2 B 1
3 C 0
4 D 0
5 E 0
measurement_unit_derivations
id measurement_unit_id derives_from_measurement_unit_id factor
---------------------------------------------------------------------------
1 3 1 2
2 4 2 2
3 4 3 2
4 5 4 2
此结果就是目标:
measurement_unit_id name ratio
-------------------------------------------
1 A 1
2 B 1
3 C 2
4 D 8
5 E 16
这是创建这两个表及其内容的快速而肮脏的SQL。
CREATE TABLE `measurement_units` (`id` int(10) UNSIGNED NOT NULL, `name` varchar(190) NOT NULL, `is_base_unit` tinyint(3) UNSIGNED NOT NULL);
CREATE TABLE `measurement_unit_derivations` (`id` int(10) UNSIGNED NOT NULL, `measurement_unit_id` int(10) UNSIGNED NOT NULL, `derived_from_measurement_unit_id` int(10) UNSIGNED NOT NULL, `factor` int(10) UNSIGNED NOT NULL);
INSERT INTO `measurement_units` (`id`, `name`, `is_base_unit`) VALUES (1, 'A', 1), (2, 'B', 1), (3, 'C', 0), (4, 'D', 0), (5, 'E', 0);
INSERT INTO `measurement_unit_derivations` (`id`, `measurement_unit_id`, `derived_from_measurement_unit_id`, `factor`) VALUES (1, 3, 1, 2), (2, 4, 2, 2), (3, 4, 3, 2), (4, 5, 4, 2);
答案 0 :(得分:0)
您已经正确设置了递归种子。我们从base_unit = 1
开始。
UNION ALL
之后的下一部分是递归项。在这里,您可以参考cte并将其连接到源表中,从而建立迭代关系。
您的递归术语将采用以下形式:
SELECT
mu.id,
mu.name,
cte.ratio * mud.factor
FROM
cte
INNER JOIN measurement_unit_derivations mud
ON cte.measurement_unit_id = mud.derives_from_measurement_unit_id
INNER JOIN measurement_units mud
ON mud.measurement_unit_id = mu.id
这将为从二维或多个维导出的测量创建多个记录。由于规则似乎是我们将多个导出的测量值相乘以确定比率(链*犁沟=英亩),因此我们可以在完成此递归cte后进行汇总。
诀窍在于,没有像加法(SUM()
)这样的乘法聚合。因此,我们必须对其进行数学计算。我相信以下方法会起作用:
SELECT measurement_unit_id, name, EXP(SUM(LOG(ratio))) FROM cte GROUP BY measurement_unit_id, name;
将所有内容放在一起:
WITH RECURSIVE cte AS (
SELECT
measurement_unit_id
name,
1 AS ratio
FROM measurement_units
WHERE base_unit = 1
UNION ALL
SELECT
mu.id,
mu.name,
cte.ratio * mud.factor
FROM
cte
INNER JOIN measurement_unit_derivations mud
ON cte.measurement_unit_id = mud.derives_from_measurement_unit_id
INNER JOIN measurement_units mud
ON mud.measurement_unit_id = mu.id
)
SELECT measurement_unit_id, name, EXP(SUM(LOG(ratio))) FROM cte GROUP BY measurement_unit_id, name;