多对多关系中的SELECT查询未显示所有“标签”

时间:2016-08-02 20:51:59

标签: mysql

我已经在这个问题上工作了几个小时了。我有两个表animalscharacteristics,它们具有多对多关系并形成第三个表animal_char。在表animal_char中,AID是表animals中ID的外键,CID是表characteristics中ID的外键。 characteristics也有一个描述属性,这就是我要搜索的内容。我的目标是能够在characteristics中搜索一个,两个或三个描述,并让输出显示包含这些描述的每个动物ID的行。此外,我希望能够看到每个动物ID的所有其他特征描述,即使我没有搜索它们。

我尝试了无数的查询,但这里有一个不起作用的例子:

SELECT a.ID, 
       a.name, 
       GROUP_CONCAT(c.description ORDER BY c.description SEPARATOR ', ') 
FROM animals a 
    INNER JOIN animal_char ac ON ac.AID = a.ID
    INNER JOIN characteristics c ON c.ID = ac.CID 
WHERE c.description = 'Lab' 
GROUP BY ID;

此代码出现问题:

  1. 我只能搜索一个特征描述
  2. 结果只显示实验室是一个特征;它们没有显示每一行的任何其他特征。我希望能够看到某些行具有多个特征。
  3. 提前非常感谢你!

    修改 好吧,我想出了一次搜索一个特征的查询。我可能会说这对于这个项目来说已经足够了。查询是:

    SELECT a.ID, a.name,
    GROUP_CONCAT(c.description ORDER BY c.description SEPARATOR ', ')
    FROM animals a 
    INNER JOIN animal_char ac ON a.ID = ac.AID
    INNER JOIN characteristics c ON c.ID = ac.CID
    WHERE a.ID IN
    (SELECT ac.AID FROM characteristics c
    INNER JOIN animal_char ac ON ac.CID = c.ID
    WHERE c.description = 'Lab')
    GROUP BY a.ID
    

2 个答案:

答案 0 :(得分:2)

您的问题是,您的查询仅包含description = 'Lab'特征,其中可能有这些动物的其他特征已完全被您的Where子句排除。

您需要做的是将过滤器与您要查找的数据分开。 这样做的一种方法是两次加入特征表。一次为过滤器(fc),一次为结果(c)。

SELECT a.ID, 
   a.name, 
   GROUP_CONCAT(c.description ORDER BY c.description SEPARATOR ', ') 
FROM animals a 
    INNER JOIN animal_char ac ON ac.AID = a.ID
    INNER JOIN characteristics c ON c.ID = ac.CID 
    INNER JOIN characteristics fc on ac.CID = fc.ID
WHERE fc.description = 'Lab' 
GROUP BY a.ID;

当您发现编辑时,还有其他方法可以执行此操作。我已经多年没有使用mysql了,所以我不会试图评论这些技术的相对优点。

答案 1 :(得分:1)

我看到一些有用的方法来进行连接(具有组合特征的动物):

SELECT a.ID, a.name,
GROUP_CONCAT(c.description ORDER BY c.description SEPARATOR ', ')
FROM animals a 
INNER JOIN animal_char ac ON a.ID = ac.AID
INNER JOIN characteristics c ON c.ID = ac.CID
WHERE a.ID IN
      (SELECT ac.AID FROM characteristics c
       INNER JOIN animal_char ac ON ac.CID = c.ID
       WHERE c.description = 'Lab' 
          OR c.description = 'second' 
          OR c.description = 'third'
       GROUP BY ac.AID
       HAVING COUNT(c.description) = 3)
GROUP BY a.ID

在您的子查询中,将按所需的描述进行过滤,然后按动物ID分组,并再次过滤那些具有所需描述数量的那些。 (但描述必须不同)这也允许一些" 2个3个特征"搜索。如果您需要它们......

第二种方法是多重的:

SELECT a.ID, a.name,
GROUP_CONCAT(c.description ORDER BY c.description SEPARATOR ', ')
FROM animals a 
INNER JOIN animal_char ac ON a.ID = ac.AID
INNER JOIN characteristics c ON c.ID = ac.CID
WHERE a.ID IN
      (SELECT ac.AID FROM characteristics c
       INNER JOIN animal_char ac ON ac.CID = c.ID
       WHERE c.description = 'Lab')
  AND a.ID IN
      (SELECT ac.AID FROM characteristics c
       INNER JOIN animal_char ac ON ac.CID = c.ID
       WHERE c.description = 'second')
  AND a.ID IN
      (SELECT ac.AID FROM characteristics c
       INNER JOIN animal_char ac ON ac.CID = c.ID
       WHERE c.description = 'third')
GROUP BY a.ID

或正如Mindor先生所建议的那样(我觉得这更平易近人,当然也把它放在where子句中):

SELECT a.ID, 
   a.name, 
   GROUP_CONCAT(c.description ORDER BY c.description SEPARATOR ', ') 
FROM animals a 
    INNER JOIN animal_char ac ON ac.AID = a.ID
    INNER JOIN characteristics c ON c.ID = ac.CID 
    INNER JOIN characteristics fc1 ON ac.CID = fc1.ID AND fc1.description = 'Lab'
    INNER JOIN characteristics fc2 ON ac.CID = fc2.ID AND fc2.description = 'second'
    INNER JOIN characteristics fc3 On ac.CID = fc3.ID AND fc3.description = 'third'
GROUP BY a.ID;

我不确定这三者中哪一个实际上是最高效的。所以你可能会尝试......或不。 ^^