Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 多次使用LEFT JOIN只能产生一行_Mysql_Sql_Join_Left Join_Outer Join - Fatal编程技术网

Mysql 多次使用LEFT JOIN只能产生一行

Mysql 多次使用LEFT JOIN只能产生一行,mysql,sql,join,left-join,outer-join,Mysql,Sql,Join,Left Join,Outer Join,它是一个基于智能标签的图像搜索系统。用户在这样的表中添加带有适当标记的图像: 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表中。(请注意,我在重复更新时使用了一个IN

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

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
查询。)


现在请考虑以下标签的图像:

  • 河流
    (这是一张阳光明媚的河流图片)
  • (午夜月光下的那条河)
用户搜索标签
河流
,并显示带有标签河流的任何图像:在这种情况下,显示第一幅图像(由河流白天标记)和第二幅图像(由河流夜晚标记)。用户查看第二张图像(由
河流和
夜晚标记),并查看记录在表
usertagview
中的图像

然后用户尝试新的搜索标签
,并查看
树夜
图像

我希望如果用户搜索
鲜花
,那么
鲜花之夜
将优先于
鲜花之日
。我的意思是花之夜应该在花之日之前到来。换句话说,我需要一个查询,根据用户以前的视图列出由
flower
标记的图像。(
花卉之夜
第一个,其他
花卉
下一个

我的查询失败:

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
问题
我的查询中的
**左连接**
与正常的
内部连接没有区别。它们都有相同的结果。即使我使用了
右连接
也不会有任何区别。

您总是会得到表映像+内部连接映像标记的结果,而不考虑下一步/之后要连接什么。如果您想要更多的结果,那么您也需要左连接imagetag表。

您的
左连接的行为与
内部连接的行为相同的原因是因为您的
where
子句中有关于
左连接的附加条件。这实际上将
外部联接
转换为
内部联接

这是因为如果
usertagview.tag\u id
NULL
,则在没有匹配记录的情况下,
where
子句中的
in
语句会删除带有
NULL
值的行

要更正此问题,您可以将您的
usertagview.tag\u id移动到…
签入您的加入的
ON
子句中

然而,这只是你的一半问题。您只检查用户输入的特定标记的视图,但如果我了解您的实际需求,您希望检查与任何图像相关联的任何标记的视图,该图像具有与您的搜索词匹配的标记

例如,当用户输入
flower
时,您希望首先找到标记有
flower
的任何图像,然后检查视图中该组图像的所有其他标记

我相信以下查询可以实现这一点,并且:


这是一个常见的问题。幸运的是,这是一个很容易解决的问题

看到这个了吗

LEFT JOIN usertagview ON
    usertagview.tag_id = imagetag.tag_id -- see this?
    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 -- and this?
        (SELECT tag_id FROM imagetag WHERE userimagetag.image_id = image.id)
两个条件共享同一字段,即
usertagview.tag\u id
。 因此,WHERE子句上的
usertagview.tag_id IN(从…)中选择tag_id
基本上取消了
左JOIN上的usertagview所取得的任何成功

因此,要修复您的查询,请将您的
内部联接
-y usertagview恢复为
左联接
一个,然后将usertagview条件改为联接条件:

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}

    -- moved the WHERE condition here
    AND
    usertagview.tag_id IN
        (SELECT tag_id FROM imagetag WHERE userimagetag.image_id = image.id)


WHERE

    imagetag.tag_id IN ( {impolde(',', $array_of_id_of_tags_that_the_user_has_entered)} )

ORDER BY SUM_of_all_tag_views_for_each_image DESC
那会解决的。如果不是(因为我不知道在您的表中,哪些是一对多,哪些是一对一,所以在本例中,我将抛出通常有效的方法),请尝试将
内部联接imagetag
更改为
左联接
。由于WHERE子句中的
imagetag
条件将抵消
LEFT JOIN
条件产生的任何行,因此也将
imagetag
条件从
WHERE
子句移动到
LEFT JOIN

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)

LEFT JOIN imagetag ON imagetag.image_id = image.id
    -- WHERE clause condition moved here.
    -- WHERE conditionXXX basically cancels out whatever rows
    -- obtained from `LEFT JOIN ON conditionXXX`, in which conditionXXX share
    -- the same field.  IN this case, it is imagetag.
    AND    
    imagetag.tag_id IN ( {impolde(',', $array_of_id_of_tags_that_the_user_has_entered)} )


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

 -- moved here
    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

如果第二个建议仍然不能提供结果,那么您的查询当前正在处理多个一对多表关系。如果在查询中有多个一对多表关系,SQL无法理解您的意图;在这种情况下,需要将结果展平以获得正确的输出。下面是一个很好的演练,介绍如何使结果平坦化:

谢谢,但是
LEFT JOIN imagetag
也不起作用。换句话说,我有3个左连接,但这不是答案,+1,因为我根本不关心它的重要性。现在我应该做更多的工作。谢谢你:)太好了。现在它就像一个符咒。sqlfiddle也确实起到了作用,因为我不得不对它进行一些更改!我真的需要函数
IFNULL
,我相信我应该学习更多关于高级查询功能的知识,就像您已经使用了两次
imagetag
一样。有教学高级查询的网站/PDF吗?这对我真的很有帮助。因为我还没有深入理解您在查询中使用的逻辑。我会更感激任何先进的mysql查询教程或PDF。感谢you@smhnaji我认为你已经走上了正确的道路。。。在查询中,正确地使用了内部联接和外部联接。这个查询中唯一棘手的部分是两次加入同一个表,这是人们忘记的
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}

    -- moved the WHERE condition here
    AND
    usertagview.tag_id IN
        (SELECT tag_id FROM imagetag WHERE userimagetag.image_id = image.id)


WHERE

    imagetag.tag_id IN ( {impolde(',', $array_of_id_of_tags_that_the_user_has_entered)} )

ORDER BY SUM_of_all_tag_views_for_each_image DESC
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)

LEFT JOIN imagetag ON imagetag.image_id = image.id
    -- WHERE clause condition moved here.
    -- WHERE conditionXXX basically cancels out whatever rows
    -- obtained from `LEFT JOIN ON conditionXXX`, in which conditionXXX share
    -- the same field.  IN this case, it is imagetag.
    AND    
    imagetag.tag_id IN ( {impolde(',', $array_of_id_of_tags_that_the_user_has_entered)} )


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

 -- moved here
    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