一尘不染

多次使用LEFT JOIN仅带来1行

sql

它是一个智能的基于标签的图像搜索系统。用户在这样的表中添加带有适当标签的图像:

image (id, title, ...)
tag (id, title) /* It doesn't matter who has created the tag*/
imagetag (image_id, tag_id) /* One image may have multiple tags */

用户查看图像,并且 来自 这些图像标签 访问 记录在usertagview表中。(请注意,我INSERT ON DUPLICATE UPDATE为此使用了查询。)

usertagview (user_id, tag_id, view_count)

现在,请考虑一些带有以下标签的图像:

  • riverday(这是一张显示晴天的河流的图片)
  • rivernight(午夜月亮照耀下的那条河)
  • treeday
  • treenight
  • flowerday
  • flowernight

用户搜索标签,river并显示带有标签 river的 所有图像:在这种情况下,将显示第一个图像(标有 river day
)和第二个图像(标有 river night )。用户 查看
第二个图像(用river和标记night),并查看将其记录在表中usertagview

然后,用户尝试对标签进行新搜索tree并查看tree night图像。

我希望如果用户搜索flower,则flower night首选flower day。我的意思是flower night应该来flower day。换句话说,我想要一个查询,该查询列出flower根据用户以前的视图标记的图像。( flower night
首先是OTHERflower的下一个
)。

我的查询失败了:

SELECT

    DISTINCT (image.id) AS image_id,
    image.title AS image_title,
    SUM(usertagview.view_count) AS SUM_of_all_tag_views_for_each_image

FROM (image)

JOIN imagetag ON imagetag.image_id = image.id

**LEFT JOIN** usertagview ON
    usertagview.tag_id = imagetag.tag_id
    AND usertagview.user_id = {$user_id_from_php}

WHERE

    imagetag.tag_id IN ( {impolde(',', $array_of_id_of_tags_that_the_user_has_entered)} )
    AND
    usertagview.tag_id IN
        (SELECT tag_id FROM imagetag WHERE userimagetag.image_id = image.id)

ORDER BY SUM_of_all_tag_views_for_each_image DESC

问题

**LEFT JOIN** 我的查询中的与正常值没有区别 INNER JOIN 。他们都有相同的结果。即使我使用
RIGHT JOIN 它也不会有任何区别。


阅读 161

收藏
2021-05-30

共1个答案

一尘不染

left join与的行为相同的原因是,您的子句中inner join包含其他条件。这实际上使您变成了。left join``where``outer join``inner join

这样做的原因是因为,如果usertagview.tag_idNULL在没有匹配记录的情况下,你的IN你在声明中WHERE条款消除了与该行NULL的值。

要更正此问题,您可以将usertagview.tag_id IN ...支票移到join的ON子句中。

但是,这只是您问题的一半。您只需要检查用户输入的特定标签的视图,但是如果我了解您的实际要求,则想检查与包含与您的搜索字词匹配的标签的任何图像相关联的所有标签的视图。

例如,当用户输入时flower,您要首先查找带有标记的任何图像,flower然后检查该图像集的所有其他标记的视图。

我相信以下查询可以完成此操作,并且此SQL Fiddle显示了正在使用的查询

SELECT
  i.id AS image_id,
  i.title AS image_title,
  IFNULL(SUM(utv.view_count), 0) AS associated_view_totals
FROM
  imagetag originalTag
  JOIN imagetag associatedTags 
    ON associatedTags.image_id = originalTag.image_id
  JOIN image i 
    ON i.id = associatedTags.image_id
  LEFT JOIN usertagview utv 
    ON utv.user_id = 1
    AND utv.tag_id = associatedTags.tag_id
WHERE
  -- User searches for flower tag (Let's assume 5 == flower)...
  originalTag.tag_id IN (5)
GROUP BY
  i.id,
  i.title
ORDER BY 
  associated_view_totals DESC
2021-05-30