在mysql循环中运行另一个查询是否安全?

时间:2016-05-20 07:32:54

标签: php mysql

我有一个左连接查询来获取用户喜欢的帖子。如果第二次登录用户访问,第一个用户个人资料将显示第一个用户的喜欢,如果第二个用户(登录用户)像同一个帖子那样也会在帖子上显示文字

用户表

user_id | username

喜欢桌子

like_id | post_id | uid 

的MySQL

$SQL = "SELECT * FROM  likes LEFT JOIN users ON users.user_id = likes.uid WHERE likes.uid = 'user1'"

如果我在上面查询的while循环中运行另一个查询,它将起作用

$check_id = row['post_id']; //get post id from 1st loop

if(isset($_SESSION['userid'])){

    $check = "SELECT * FROM  likes WHERE post_id='$check_id' AND uid='LOGED-IN-USER-ID'"

}

然后我可以获得num_rows并添加文字。这项工作非常好但我想知道有没有更好的方法来做到这一点,而不在while循环中运行这么多的查询。有没有办法组合查询或在循环外执行第二个查询。

2 个答案:

答案 0 :(得分:2)

那"安全"来自"数据一致性的观点",但在查询后的一段时间内查询称为" 1 + N"并且通常是性能杀手,您可以轻松找到有关SQL 1 + N问题的文档。

解决方案是让SQL服务器在单个查询中为您完成工作,避免与它一起打乒乓球(读取:来回的TCP数据包,查询解析,......)。

假设:

> SELECT * FROM user;
+---------+----------+
| user_id | username |
+---------+----------+
|       1 | root     |
|       2 | user2    |
|       3 | user3    |
+---------+----------+


> SELECT * FROM `like`;
+---------+---------+---------+
| like_id | post_id | user_id |
+---------+---------+---------+
|       1 |       1 |       1 |
|       2 |       2 |       1 |
|       3 |       3 |       1 |
|       4 |       4 |       1 |
|       5 |       2 |       2 |
+---------+---------+---------+

> SELECT * FROM `post`;
+---------+--------+
| post_id | text   |
+---------+--------+
|       1 | post 1 |
|       2 | post 2 |
|       3 | post 3 |
|       4 | post 4 |
+---------+--------+

有多种方式可以请求您想要的内容,但有一种方法可能是:

> SELECT like_id, like.post_id, text,
         (SELECT 1 FROM `like`
           WHERE post_id = post.post_id AND
                 user_id = 2 /* logged in user */) AS I_like_it_too
    FROM `like`
    JOIN post USING (post_id)
   WHERE user_id = 1 /* user id of seen profile  */;

+---------+---------+--------+---------------+
| like_id | post_id | text   | I_like_it_too |
+---------+---------+--------+---------------+
|       1 |       1 | post 1 |          NULL |
|       2 |       2 | post 2 |             1 |
|       3 |       3 | post 3 |          NULL |
|       4 |       4 | post 4 |          NULL |
+---------+---------+--------+---------------+

使用I_like_it_too别名根据需要以不同方式显示帖子。

从性能的角度来看,您需要like.user_id上的索引来限制一小部分上的选定行,依赖子查询只会针对此子集运行,因此这样做了行。

另一种可能性是:

>  SELECT displayed.like_id, displayed.post_id, text, my_likes.like_id is not null AS i_also_like
     FROM `like` AS displayed
     JOIN post USING (post_id)
LEFT JOIN `like` AS my_likes ON
          displayed.post_id = my_likes.post_id AND
          my_likes.user_id = 2 /* logged user */
    WHERE displayed.user_id = 1 /* user id of seen profile  */;

+---------+---------+--------+-------------+
| like_id | post_id | text   | i_also_like |
+---------+---------+--------+-------------+
|       1 |       1 | post 1 |           0 |
|       2 |       2 | post 2 |           1 |
|       3 |       3 | post 3 |           0 |
|       4 |       4 | post 4 |           0 |
+---------+---------+--------+-------------+

答案 1 :(得分:0)

你的意思是这样吗?

表SO_LIKES(你"喜欢"表)

like_id | post_id | uid
      1 |       1 | 1
      2 |       2 | 1
      3 |       1 | 2

表SO_USERS(您"用户"表)

   user_id | username 
         1 | User1 
         2 | User2 

SQL

SELECT * FROM SO_LIKES as t1 LEFT JOIN SO_USERS as t2 ON t1.uid = t2.user_id INNER JOIN SO_LIKES as t3 ON t1.post_id = t3.post_id WHERE t2.user_id = 1 AND t3.uid = 2

SO只需再次在您的查询中调用相同表,并使用用户2的ID

WHERE t2.user_id = 1 AND t3.uid = 2

输出看起来像这样

like_id | post_id | uid | user_id | username | like_id | post_id | uid 
      1 |       1 |   1 |       1 |    User1 |       3 |       1 | 2 

所以你得到了POST_id 1这两个用户都喜欢