关于php:尝试加入一个空表没有返回

Trying to JOIN an empty table nothing returns

尝试将空表(注释表)联接到现有的已准备语句时出现问题。

这非常有效:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// prepare images
if ($stmt = $mysqli->prepare("  SELECT uu.*, m.*,
                                                (
                                                    SELECT COUNT(*)
                                                    FROM img_likes AS t
                                                    WHERE t.img_id = uu.imgID AND t.user_id = ?
                                                ) AS user_likes,
                                                (
                                                    SELECT COUNT(*)
                                                    FROM img_likes AS t
                                                    WHERE t.img_id = uu.imgID
                                                ) AS total_likes
                                FROM user_uploads AS uu
                                INNER JOIN members AS m ON m.id = uu.user_id
                                ORDER BY up_time DESC"
)) {
    $stmt->bind_param('i', $user_id);
    $stmt->execute(); // get imgs

    // foreach print images
    // working as expected
}

我不知道为什么如果我加入另一个空的表格(img_comments),图像就不会被打印出来…如果我在表格中添加一行并刷新页面,就会打印一个图像…

我正在尝试但不起作用的声明是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SELECT uu.*, m.*, ic.*,
                (
                    SELECT COUNT(*)
                    FROM img_likes AS t
                    WHERE t.img_id = uu.imgID AND t.user_id = ?
                ) AS user_likes,
                (
                    SELECT COUNT(*)
                    FROM img_likes AS t
                    WHERE t.img_id = uu.imgID
                ) AS total_likes
FROM user_uploads AS uu
INNER JOIN members AS m ON m.id = uu.user_id
INNER JOIN img_comments AS ic ON ic.img_id = uu.imgID
ORDER BY up_time DESC

为什么只打印基于表行数的图像?我也试过左进,但我不太熟悉这个。我只在其他脚本中使用内部联接,而且从未遇到过这样的问题。

我希望对我的查询进行任何优化。


内部联接的作用是什么?它将表A的所有记录与表B的所有匹配记录连接起来,因此当表B中没有记录时,表A的任何记录都不匹配,因此根本没有结果。为什么这会让你吃惊?

左联接是外部联接(左外部联接的简称)。意思是:给我A表的所有记录和B表的所有匹配记录,当没有匹配时,无论如何给我A表的记录。这似乎是你想要的。但你说你试过了。我看不出这在你的问题上会怎样失败。

外部连接不工作的一个典型错误是在WHERE子句中有一些字段b(例如,当b.id>100时)。由于外部联接的记录没有匹配的B记录,因此所有B字段都为空,因此这样的WHERE子句将失败。你只需要再次得到匹配,就像内部连接一样。

编辑:关于优化,可以有条件地一次通过计数得到两个计数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SELECT
  uu.*, m.*, ic.*,
  il.count_user AS user_likes,
  il.count_total AS total_likes
FROM user_uploads AS uu
INNER JOIN members AS m ON m.id = uu.user_id
LEFT OUTER JOIN img_comments AS ic ON ic.img_id = uu.imgID
LEFT OUTER JOIN
(
  select
    img_id,
    count(*) as count_total,
    count(case when t.user_id = ? then 1 end) as count_user
  from img_likes
  group by img_id
) AS il ON il.img_id = uu.imgID
ORDER BY uu.up_time DESC;


据我所知,内部联接将只检索同时具有这两个数据的数据。因此,假设您所联接的表没有具有该联接条件的数据。它不会返回任何数据。

左联接只是普通联接。它将检索两个表上的数据。但是,如果联接的表为空,那么只有主表才有数据,次表的数据将为空。

您只需修改代码,用左联接替换内部联接,然后看看它是否工作。/