多对多SQL关系:如何在一个查询中检索所有相关条目?

时间:2010-07-15 14:23:28

标签: php mysql many-to-many

我有与此问题相同的表格:MySql query over many-to-many relationship。 然而,我正在努力的是如何构建一个查询来获得具有其所有属性的工厂。即如果我想要P1我

P1 | A1 | A2 | A3 or P1 | A1, A2, A3

相反
P1 | A1
P1 | A2
P1 | A3

如果我想要所有植物,我会

P1 | A1 | A2 | A3          P1 | A1, A2, A3
P2 | A1 | A2         or    P2 | A1, A2
P3 | A2 | A3               P3 | A2, A3

反之亦然,即显示给定参数的所有植物。首先 - 是否可以创建这样的SQL查询?

我目前所拥有的是每次获取每个植物一次,每次访问数据库时再次询问属性。你可能已经意识到效率非常低,所以我希望你能指出我正确的方向。

编辑:我想在每一行中获得一个工厂,并在同一行中获得所有属性。

5 个答案:

答案 0 :(得分:3)

你的意思是如下吗?我通过删除链接表简化了一些事情,但想法是一样的:

SELECT
  plant.name,
  GROUP_CONCAT(attrib.name) AS attribs
FROM plant
JOIN attrib ON attrib.plant_id = plant.id
GROUP BY plant.id;

+------+----------------+
| name | attribs        |
+------+----------------+
| P1   | A1-1,A1-2,A1-3 |
| P2   | A2-1,A2-2,A2-3 |
| P3   | A3-1,A3-2,A3-3 |
+------+----------------+

或者这个:

SELECT plant.name, GROUP_CONCAT(attrib.name)
FROM plant JOIN attrib
ON attrib.plant_id = plant.id
WHERE attrib.name IN ('A2-1', 'A2-3', 'A3-2')
GROUP BY plant.id;

+------+---------------------------+
| name | GROUP_CONCAT(attrib.name) |
+------+---------------------------+
| P2   | A2-1,A2-3                 |
| P3   | A3-2                      |
+------+---------------------------+

以上内容来自以下插页:

INSERT INTO plant (name) VALUES
  ('P1'), ('P2'), ('P3');

INSERT INTO attrib (plant_id, name) VALUES
  (1, 'A1-1'), (1, 'A1-2'), (1, 'A1-3'),
  (2, 'A2-1'), (2, 'A2-2'), (2, 'A2-3'),
  (3, 'A3-1'), (3, 'A3-2'), (3, 'A3-3');

答案 1 :(得分:1)

你已经标记了这个PHP,所以让我们用PHP来解决这个问题。 $dbPDO连接的位置,表结构如knittl's comment中所定义:

$plant_id = 1;
$plant_attributes = array();
$query = "knittl's query from above, because it works well enough for us.";
$sth = $db->prepare($query);
$sth->execute($plant_id);
while($row = $sth->fetch(PDO::FETCH_ASSOC))
    $plant_attributes[] = $row['attrid'];

多田!您现在拥有所选工厂的所有属性的列表。对于所有植物:

$plant_attributes = array();
$query = "knittl's query from above, minus the WHERE clause";
$sth = $db->prepare($query);
$sth->execute();
while($row = $sth->fetch(PDO::FETCH_ASSOC))
    $plant_attributes[ $row['plantid'] ][] = $row['attrid'];

多田!您现在拥有所有植物及其属性的列表。

您最初要求的内容类似于“pivot table”或“crosstab”。 MySQL不能做你原生要求的事情。有可能创建一个存储过程尝试以表格格式返回数据,而不是像数据库中存在的面向列的格式,但这是一个令人难以置信的痛苦。另一方面,这并不是一种令人难以置信的痛苦。

答案 2 :(得分:0)

只需加入他们:

    select p.*, a.*
      from plants p
inner join plantattributes pa
        on p.plantid = pa.plantid
inner join attributes a
        on pa.attrid = a.attrid
     where pa.plantid = ?

如果您希望给定属性的所有植物都使用where a.attrid = ?

答案 3 :(得分:0)

我认为你应该使用数据库程序而不是查询,但我不太熟悉mysql程序,所以我不能用它来帮助你。但我希望这会给你新的思考方向,也许你会找到解决方案:)

答案 4 :(得分:0)

此查询将返回所有植物及其属性。此问题中的表格MySql query over many-to-many relationship

SELECT `Plant`.`name`,
GROUP_CONCAT(`Attribute`.`name`) AS attribs
FROM `plant`, `attribute`, `hasAttribute`
WHERE `Plant`.`pid` = `hasAttribute`.`pid`
AND `Attribute`.`aid` = `hasAttribute`.`aid`
GROUP BY `Plant`.`name`

应该返回:

+------+----------+
| name | attribs  |
+------+----------+
| P1   | A1,A2,A3 |
| P2   | A1,A2    |
| P3   | A2,A3    |
+------+----------+