使用联接表中的值跨多个表联接
Posted
技术标签:
【中文标题】使用联接表中的值跨多个表联接【英文标题】:Join across multiple tables using values from joined tables 【发布时间】:2012-10-22 06:26:16 【问题描述】:我有以下表格:
systems
-----------
id
name
price
online
productid
specifications
-------------
id
systemid
type
componentid
quantity
components
-------------
id
name
brand
type
description
我需要使用多个选项过滤这些表。每个系统都有多个规格行,每个“规格”行都链接到相应的“组件”行。
我的问题是这样的:
我需要能够根据表连接按多个属性过滤系统。我一直在使用允许我有 1 个搜索选项的代码,但没有更多:
select
`systems`.`id`,
`systems`.`name`,
`specifications`.`type`
from `systems`
join specifications
on `systems`.`id` = `specifications`.`systemid`
join components
on `specifications`.`componentid` = `components`.`id`
where
`specifications`.`type` = 'cpu'
and `components`.`brand` = 'amd'
所以,这将让我在规格类型为 CPU 且品牌为 AMD 的情况下进行连接,但如果我也添加其他要查找的内容,例如 specifications.type ='graphics' AND components.brand = 'nvidia'
,它将无法正常工作。我认为这是 join 工作方式所固有的,正如我所说,我无法在这里阐明这个问题,因为我对这些更复杂的数据库事务很陌生,并且非常感谢您指出正确的方向!
我使用 CodeIgniter 作为我的框架,我想尝试通过 mysql 来了解这个问题,而不是在可能的情况下在 php 中进行 - 因为我想更好地了解正在发生的事情在这里。
【问题讨论】:
如何将specifications.type ='graphics' AND components.brand = 'nvidia'
添加到您的子句中?当你运行它时,你得到了什么结果?
它与问题无关,但可能有用。我建议您将列 systemid 重命名为 systems_id。您可以使用像这样 (tablename_id) 这样命名的外键列轻松迁移到 DataMapper。
@andrewsi 我只是在底部添加了额外的“AND”语句,所以想象上面的语句带有“AND specifications
.type
= 'graphics' and components
.brand
= 'nvidia'。似乎 Darrrren 将 where 语句组合在一起的答案(如下)似乎朝着正确的方向发展,但在运行带有两个 where 子句的语句时不起作用。
【参考方案1】:
你的意思是说
select `systems`.`id`,`systems`.`name`, `specifications`.`type` from `systems`
join specifications on `systems`.`id` = `specifications`.`systemid`
join components on `specifications`.`componentid` = `components`.`id`
where
(`specifications`.`type` = 'cpu' AND `components`.`brand` = 'amd') OR
(`specifications`.`type` = `graphics` AND `components`.`brand` = `nvidia`)
不工作?
这样的事情呢
SELECT S.`id`, S.`name`, P.`type` FROM `systems` S
JOIN `specifications` P ON S.`id` = P.`systemid`
WHERE S.`id` IN (
SELECT S2.`systemid` AS id FROM `specifications` S2
JOIN `components` C2 ON S2.`componentid` = C2.`id`
WHERE S2.`type` = 'cpu' AND c2.`brand` = 'amd'
) AND S.`id` IN (
SELECT S3.`systemid` AS id FROM `specifications` S3
JOIN `components` C3 ON S3.`componentid` = C3.`id`
WHERE S3.`type` = 'graphics' AND c3.`brand` = 'nvidia'
)
【讨论】:
我不知道您可以有效地“分组” where 语句。以上适用于检索具有 AMD CPU 或 NVIDIA 显卡的所有系统,但我希望它同时使用两者,我将其中的“OR”更改为“AND”,但它不会产生结果。 哈!我们似乎同时遇到了同样的问题——你的打字比我的优雅一点。我在回答中问了一些关于这样做的问题,任何帮助都将不胜感激:) 我们的查询并不完全相同——因为你嵌套的查询比我更复杂——请注意,在你的每个子查询中,你将执行两个连接——表连接很昂贵。我的解决方案的每个子查询只会执行一次连接。【参考方案2】:好的,通过让每个查询都作为子查询运行,我已经让它工作了。
因此,它将所有具有 AMD 处理器的系统的 ID 返回到查找所有具有 NVIDIA 显卡的系统的条件 IN 子句。
SELECT `systems`.`id` , `systems`.`name` , `specifications`.`type`
FROM `systems`
JOIN specifications ON `systems`.`id` = `specifications`.`systemid`
JOIN components ON `specifications`.`componentid` = `components`.`id`
WHERE (
`specifications`.`type` = 'graphics'
AND `components`.`brand` = 'nvidia'
)
AND (
`systems`.`id` IN (
SELECT `systems`.`id`
FROM `systems`
JOIN specifications ON `systems`.`id` = `specifications`.`systemid`
JOIN components ON `specifications`.`componentid` = `components`.`id`
WHERE (
`specifications`.`type` = 'cpu'
AND `components`.`brand` = 'amd'
)
)
)
从编程上讲,我觉得它很麻烦,而且我不确定它是如何提高效率的 - 作为一个基本上是自学成才的程序员,我一直在努力确保我以“正确”的方式做事.任何人都可以看到以这种方式运行它的任何问题吗?让 CodeIgniter 返回那组 ID 会更好吗?
请记住,这个问题在某种程度上被简化了,它最终将包含几个子查询 - 尽管网站本身永远不会承受巨大的负载。
【讨论】:
我不相信对这个查询使用 CodeIgniter 的 ActiveRecord 类是正确的方法,但是如果你真的想尝试将子查询破解到 ActiveRecord 中,上面有一个线程 here以上是关于使用联接表中的值跨多个表联接的主要内容,如果未能解决你的问题,请参考以下文章