sql - 如何查询表中的传递匹配?
问题描述
给出下表
单位:
| id | singular | plural |
|----|----------|--------|
| 3 | onion | onions |
| 4 | bag | bags |
| 5 | gram | grams |
| 6 | ml | ml |
| 7 | mm | mm |
和
转换:
| id | convert_from | convert_to | factor |
|----|--------------|------------|--------|
| 3 | 4 | 3 | 5 |
| 4 | 3 | 5 | 125 |
我如何从(例如)bag
(单位4
)获得所有可能的转换因子?
我希望答案类似于表格
| convert_from | convert_to | factor |
|--------------|------------|--------|
| 4 | 3 | 5 |
| 4 | 5 | 625 |
注意事项:
- 无法保证单位可能出现在转换表 (
convert_from
, ) 的哪一列。convert_to
通过单位
5
、6
或的转换7
应该被忽略。也就是说,
1->2->4->5
有效,1->2->4->5->7
无效。- 一个
SQL
解决方案(或重新构建数据库以促进 SQL 解决方案)将是理想的,但也将赞赏进行多个 SQL 查询的代码解决方案。 - 如果单位表中的其他单位不构成转换图的一部分(或者如果它们通过无效转换(、、或)构成分支的一部分),则应忽略
5
这些6
单位7
。这是一个简化的视图。
说明性示例
暂时忽略 SQL 并检索数据,这就是我想要实现的目标:
我想建立一个用户可以存储家用产品的系统。一个产品有一个与之关联的单位。单位可能是 SI 单位,例如 mm、ml、g..,也可能是离散单位,例如洋葱或罐头。
单位之间可以有关系,例如1 can -> 330 ml
. 我的问题的复杂性来自这样一个事实,即单个单元的转换可能分布在许多产品中。
再次考虑这个can
例子,我们可以有一个pepsi (crate of 24)
单位为的crate
产品,以及另一个pepsi (can)
单位为 的产品can
。
当用户创建pepsi (can)
产品时,他们提供以下转换:
1 can -> 330 ml
之后,用户创建pepsi (crate of 24)
产品,并提供以下转换:
1 crate -> 24 can
最后,用户问“我有多少百事可乐?”
我希望能够回答:
- 25罐
- 1.0417 个板条箱
- 8250 毫升。
但是,我不知道如何将 crates 转换为 ml。
这是另一个图解形式的例子:
编辑:
- 将 mms 和 mls 更改为 mm 和 ml。不知道我在想什么……
- 添加了图表以帮助阐明我在寻找什么而不是解决方案。
解决方案
假设数据中没有循环,您可以使用递归 CTE。
我添加了一个额外的is_terminal
列来标识您不想再转换的终端单元(5、6 和 7)。查询是:
with recursive
e (convert_from, convert_to, factor, is_terminal) as (
select id, id, 1, is_terminal from units where id = 4 -- bag
union all
select e.convert_from, c.convert_to, e.factor * c.factor, u.is_terminal
from e
join conversions c on c.convert_from = e.convert_to
join units u on u.id = c.convert_to
where not e.is_terminal
)
select * from e where convert_from <> convert_to
结果:
convert_from convert_to factor is_terminal
------------ ---------- ------ -----------
4 3 5 false
4 5 625 true
请参阅DB Fiddle上的运行示例。这是我用来测试的数据脚本:
create table units (
id int,
is_terminal boolean
);
insert into units (id, is_terminal) values
(3, false), (4, false),
(5, true), (6, true), (7, true);
create table conversions (
id int,
convert_from int,
convert_to int,
factor int
);
insert into conversions (id, convert_from, convert_to, factor) values
(3, 4, 3, 5),
(4, 3, 5, 125);
推荐阅读
- java - 使用 Spring MVC 时出现 404
- java - 在导航片段中设置标签对齐
- haskell - 为什么 Haskell 查找函数会导致自定义数据类型出现非详尽模式错误?
- python - Python中“set”和“if item in array”的时间复杂度是多少?
- python - Python,PyTest 是否可以同时添加长参数和短参数?
- vb.net - 处理 WaitForSingleObject - 响应式 UI
- database - 在 PostgreSQL 中存储唯一和非唯一视图/使用统计信息的最佳方式
- reactjs - 使用 react native paper 和 react native navigation v5 将道具从堆栈导航器下的屏幕传递到共享应用栏
- assembly - NASM。如何使用在有效地址上不断变化的变量?
- javascript - 使用树结构 React JS 中的数据在下拉菜单中搜索