正确的方法来连接mysql中的表以获得单个结果

时间:2014-01-14 23:31:47

标签: php mysql sql

所以我有一个包含三个表的mysql数据库有三个表我试图根据数据content的条件从phpro_tag_types检索数据行

表格的结构是这样的

phpro_tag_types

tag_type_id | tag_type_name
  <pk>

phpro_tag_targets

tag_target_id | tag_id | sub_tag_id | tag_target_name | tag_type_id
    <pk>      |  <FK>  |    <FK>    |                 |    <FK>

含量

   content_id | tag_target_id | bunch of other things|
    <pk>      |    <fk>       |

表之间的关系就像这样

content.tag_target_id : phpro_tag_targets.tag_target_id 
      1  :  m   //each tag_target_id is in content once 
                //and phpro_tag_targets many times   

phpro_tag_targets.tag_type_id : phpro_tag_types.tag_type_id
                             M: 1   // there is many occurrences of tag_type_id 
   //in phpro_tag_targets and one occurrence in of tag_type_id in phpro_tag_type

(我希望我已经用正确的术语对此进行了彻底的解释,如果不是我道歉,显然我对此仍然很绿)

现在我有一个看起来像这样的SQL查询

SELECT *
FROM phpro_tag_types types
INNER JOIN phpro_tag_targets targets ON types.tag_type_id=targets.tag_type_id
INNER JOIN content c ON targets.tag_target_id = c.tag_target_id
WHERE types.tag_type_id=14
ORDER BY update_time DESC

现在这个查询的工作原理并不完全符合我的预期。问题是返回的结果数组具有相同内容的多个实例,即。一个content_id(我相信因为tag_target_id多次存在phpro_tag_targets}但是我只希望结果数组只包含唯一的content_id,因为这是我实际输出给用户的数据。

作为旁注,将Distinct放入查询中似乎也不起作用,因为无法确保contentDISTINCT(至少我能找到)

任何对此的帮助都将非常感激,因为我对如何实现这一目标感到失望

2 个答案:

答案 0 :(得分:1)

  

“我正在尝试根据数据条件从内容中检索数据行 phpro_tag_types

假设您正在尝试获取content的字段。如何关注IN()子查询

SELECT *
FROM content c
WHERE tag_target_id IN (
    SELECT DISTINCT tag_target_id
    FROM phpro_tag_types types
    INNER JOIN phpro_tag_targets targets ON types.tag_type_id=targets.tag_type_id
    WHERE types.tag_type_id=14
)
ORDER BY update_time DESC;

顺便说一句,

  

“作为旁注,将Distinct放入查询中也似乎没有用,因为没有办法只确保内容是DISTINCT(至少我能找到)”

DISTINCT c.*没有意义吗?

SELECT DISTINCT c.*
FROM phpro_tag_types types
INNER JOIN phpro_tag_targets targets ON types.tag_type_id=targets.tag_type_id
INNER JOIN content c ON targets.tag_target_id = c.tag_target_id
WHERE types.tag_type_id=14
ORDER BY update_time DESC;

答案 1 :(得分:0)

在复制表上执行左外连接的一般技巧是只有一个条目具有空值,然后将查询限制到该行:

SELECT * 
FROM phpro_tag_types types 
INNER JOIN phpro_tag_targets targets ON types.tag_type_id=targets.tag_type_id 
INNER JOIN content c ON targets.tag_target_id = c.tag_target_id 
LEFT OUTER JOIN phpro_tag_targets t2 on targets.tag_target_id=t2.tag_target_id
    AND t2.tag_id < targets.tag_id 
WHERE types.tag_type_id=1
    AND t2.tag_target_id IS NULL;

这似乎有点疯狂,但确实有效,而且根据我的经验,除非你处理一个非常大的&#39;数据集(无论这意味着什么)。

我并不是100%确定这里的语义是什么,但是这个问题假设你不关心什么&#39; tag_id&#39;你知道,你只想得到任何与&#39; type_id&#39;相匹配的标签,它看起来符合你的意图。

注意:这会在&#39; *&#39;中导致重复的列名称选择,因此您需要限制为types.*, targets.*, content.*或拼出列名称。