是的,有点愚蠢的称号,但我发现很难描述我的问题。我有以下表格:
id | name
1 | color
2 | material
id | property_id | name
1 | 1 | yellow
2 | 1 | blue
3 | 2 | wood
4 | 2 | stone
id | name
1 | orange juice
2 | cheese
id | substance_id | option_id
1 | 2 | 1
2 | 2 | 3
3 | 1 | 1
现在,我有一个选项列表,想知道哪些物质与所有这些选项有关。 (例如,哪些物质是黄色的并且由木材制成?)这可以通过一个查询来实现吗?
我正在尝试在Rails中执行此操作。
答案 0 :(得分:0)
刚出头,你可以试试:
SELECT DISTINCT s.name FROM substances s, relation r
WHERE r.substance_id = s.id
AND r.option_id IN ( 1, 3)
答案 1 :(得分:0)
(SELECT s.name FROM substances s, relations r, options o
WHERE r.substance_id = s.id and r.option_id = o.id and o.name='yellow')
INTERSECT
(SELECT s.name FROM substances s, relations r, options o
WHERE r.substance_id = s.id and r.option_id = o.id and o.name='wood')
或者
SELECT s.name FROM substances s
WHERE exists(SELECT * from relations r, options o
WHERE r.substance_id = s.id and r.option_id = o.id and o.name='yellow')
AND exists(SELECT * from relations r, options o
WHERE r.substance_id = s.id and r.option_id = o.id and o.name='wood')
拥有一个options
表与property_id
来分辨不同类型的选项并不是一个好主意,真的让这更难。我建议将不同类型的选项分成不同的表格
MATERIALS(id,name)
COLORS(id,name)
并为每种类型的表使用单独的关系。在这种情况下,您不需要为每个关系使用单独的表,因为它似乎是一个(物质)到一个(颜色)关系。
SUBSTANCES(id, name, material_id, color_id)
然后您的查询更加简单
SELECT s.name FROM substances s, materials m, colors c
WHERE s.color_id = c.id AND m.material_id = m.id
AND m.name = 'wood'
AND c.name = 'yellow'
ActiveRecord应该能够比前两个更容易地处理这个最后一个查询。
答案 2 :(得分:0)
SELECT s.name
FROM substances AS s
LEFT JOIN relations AS r1
ON s.id = r1.substance_id
INNER JOIN relations AS r2
ON r1.substance_id = r2.substance_id
AND r1.option_id < r2.option_id
LEFT JOIN options AS o1
ON o1.id = r1.option_id
LEFT JOIN options AS o2
ON o2.id = r2.option_id
WHERE o1.name = 'yellow'
AND o2.name = 'wood'
我不太了解优化SQL的性能。您可能希望对上面的这个(下面)以及此处发布的其他解决方案进行基准测试。
SELECT s.name
FROM substances AS s
LEFT JOIN relations AS r1
ON s.id = r1.substance_id
INNER JOIN relations AS r2
ON r1.substance_id = r2.substance_id
AND r1.option_id < r2.option_id
LEFT JOIN options AS o1
ON o1.id = r1.option_id
AND o1.name = 'wood'
LEFT JOIN options AS o2
ON o2.id = r2.option_id
AND o2.name = 'yellow'