简体   繁体   English

如何以一对多关系联接两个表并获得COUNT()?

[英]How to join two tables with 1-to-many relationship and get COUNT()?

I am having a bit of problem with a mysql query that I am developing for a social media application in which users can post their feed/post and view number of "likes", "comments" and "shared" counts -- similar to facebook and twitter. 我为社交媒体应用程序开发的mysql查询存在一些问题,用户可以在其中发布其feed / post并查看“喜欢”,“评论”和“共享”计数的数量-与facebook类似和推特。

The part that I am having trouble with is querying feeds and getting the number of "likes" in each feed. 我遇到的问题是查询提要并获取每个提要中的“喜欢”次数。

Basically I have two tables: 基本上我有两个表:

  1. user_feeds is the table that holds the "feeds" data. user_feeds是保存“提要”数据的表。

  2. user_feed_likes holds "likes" of feeds assigned to a feed_id which relates to the id of the user_feeds table user_feed_likes保存分配feed_id user_feeds表的id相关的user_feeds的“点user_feeds

How can I query the feeds and perform an inner subquery to query the count()/ number of likes in the likes table and return the result of the two queries? 我如何查询提要并执行内部子查询来查询Likes表中的count()/点赞数并返回两个查询的结果?

The tables look like: 表格如下:

user_feeds user_feeds

| id | feed       | phone        | time_stamp |
-----------------------------------------------
| 0  | good day   | 25470159224  | 08/08/2018 |
| 1  | bad day    | 254701594224 | 08/09/2018 |
| 2  | normal day | 254701594224 | 08/10/2018 |

user_feed_likes user_feed_likes

| id | feed_id | time_stamp |
----------------------------- 
| 0  | 1       | 08/08/2018 |  
| 1  | 1       | 08/08/2018 |  
| 2  | 0       | 09/10/2018 |

I want to select the from user_feeds and get the number of likes from user_feed_likes where user_feed id = [value which is also contained in likes as feed_id] 我想从选择user_feeds并获得喜欢从数量user_feed_likes其中user_feed id = [value which is also contained in likes as feed_id]

Here is my php coding attempt that didn't work as desired. 这是我的php编码尝试,未按要求工作。

function get_post_id($con,$contact_owned,$shared_post_id,$from,$to){
    $sql="SELECT user_feeds.*,user_credentials.username,profile_pic.imagenamesized,user_feed_likes.user_feed_id AS no_likes

    FROM user_feeds 
    INNER JOIN user_credentials ON user_feeds.phone=user_credentials.phone
    INNER JOIN profile_pic ON user_feeds.phone=profile_pic.phone

    LEFT JOIN user_feed_likes ON user_feed_likes.user_feed_id
    =(SELECT count(user_feed_id)  FROM user_feed_likes WHERE user_feed_id='user_feeds.id')

    WHERE user_feeds.phone IN('".implode("','",$contact_owned)."') ORDER BY time_stamp desc  LIMIT $from,$to;";

    $result=mysqli_query($con,$sql);
    if (mysqli_num_rows($result)>0) {
        while ($rows=$result->fetch_assoc()) {
            $row_arry['id']=$rows['id'];
            $row_arry['phone']=$rows['phone'];
            $row_arry['feed']=$rows['feed'];
            $row_arry['image_1']=$rows['image_1'];
            $row_arry['image_2']=$rows['image_2'];
            $row_arry['Image_3']=$rows['Image_3'];
            $row_arry['image_4']=$rows['image_4'];
            $row_arry['time_stamp']=$rows['time_stamp'];
            $row_arry['username']=$rows['username'];
            $row_arry['imagenamesized']=$rows['imagenamesized'];
            $row_arry['no_likes']=$rows['no_likes'];

            //array_push($respond, $row_arry);

            # code...
        }
        # code...
    }

Any help of how to select a feed and get the number of likes that a feed got will be of great help. 如何选择提要并获得提要喜欢的次数的任何帮助都将有很大帮助。

I really, really don't like posting answers that I haven't tested, but for the sake of progressing this question I'll take a stab. 我确实非常不喜欢发布尚未测试的答案,但是为了解决这个问题,我会采取行动。

"SELECT
  a.id, a.feed, a.phone, a.time_stamp,
  b.username,
  c.imagenamesized,
  COUNT(d.id) AS likes
FROM user_feeds a
INNER JOIN user_credentials b ON a.phone = b.phone
INNER JOIN profile_pic c ON a.phone = c.phone
LEFT JOIN user_feed_likes d ON a.id = d.feed_id
WHERE a.phone IN ('" . implode("',', $contact_owned) . "')
GROUP BY a.id
ORDER BY a.time_stamp DESC
LIMIT $offset, $limit"

Because it is possible for user_feed_likes to contain zero "likes" for a particular feed_id , a LEFT JOIN is the correct JOIN . 因为user_feed_likes可能包含特定feed_id零个“ feed_id ,所以LEFT JOIN是正确的JOIN Your LEFT JOIN syntax should mirror your INNER JOIN s. 您的LEFT JOIN语法应镜像您的INNER JOIN

By using GROUP BY you generate aggregate data that COUNT() can happily work with. 通过使用GROUP BY您可以生成COUNT()可以轻松使用的汇总数据。

To make your query shorter and potentially easier to read, I recommend using table aliases ( a , b , c , d ). 为了使查询更短并且可能更易于阅读,我建议使用表别名( abcd )。 When declaring the aliases, you can write the AS keyword before the alias as syntactic sugar, but I think it is more common to omit it. 在声明别名时,您可以在别名之前写AS关键字作为语法糖,但是我认为更常见的是省略它。

Your $from and $to are poor choices for variable names because that is not literally the data that they hold. 您的$from$to是变量名的不佳选择,因为从字面上看,这并不是它们所保存的数据。 $from isn't terrible, but $to is potentially misleading to future readers of your code. $from并不可怕,但是$to可能会误导您的代码的未来读者。 This is why I changed it in my snippet. 这就是为什么我在代码段中更改了它。

As a matter of best practice, you should always write mysql keywords in all caps for readability. 作为最佳实践,您应该始终在所有大写形式下编写mysql关键字以提高可读性。

As a matter of best practice, you should avoid using * in your SELECT clause. 作为最佳实践,应该避免在SELECT子句中使用* Only extract the data from columns that you intend to use. 仅从您打算使用的列中提取数据。 This will allow you to loop the result set and simply push the full $row into $respond without explicitly naming each column by [key] . 这将允许您循环结果集,而只需将整个$row推送到$respond而无需通过[key]显式命名每列。

You should comb over your script again and ensure that you are consistently using object-oriented mysqli syntax. 您应该再次梳理脚本,并确保始终使用面向对象的mysqli语法。 Mixing procedural and object-oriented is not best practice. 混合过程和面向对象不是最佳实践。 I prefer object-oriented because it is more succinct. 我更喜欢面向对象,因为它更简洁。

In case you don't know, $result can be iterated directly with foreach() without calling fetch_assoc() . 如果您不知道,可以直接使用foreach()迭代$result ,而无需调用fetch_assoc()

Avoid declaring single-use variables. 避免声明一次性变量。 If you are merely pushing the data into another array, do so without intermediate variables. 如果您只是将数据推送到另一个数组中,则无需中间变量。

I don't know if your $contact_owned array (consider renaming this variable as well to better describe the data that it contains. Eg $user_phone_numbers ) is coming from a user submission, but if it is coming from a form submission or other untrusted source, then you MUST implement a prepared statement for security and stability. 我不知道您的$contact_owned数组(考虑重命名此变量以更好地描述它包含的数据。例如$user_phone_numbers )是否来自用户提交,但是否来自表单提交或其他不受信任的来源,则必须为安全性和稳定性实施准备好的语句。 See this post which speaks about building a prepared statement with a variable number of placeholders: https://stackoverflow.com/a/52323556/2943403 请参阅这篇文章,其中涉及构建具有可变数量的占位符的准备好的语句: https : //stackoverflow.com/a/52323556/2943403

If $contact_owned is derived from a prior query on the database, it would be more direct to reduce the total trips to the database and just write WHERE logic to filter the necessary user phone numbers using a user id or something instead of your current IN logic. 如果$contact_owned是从数据库上的先前查询派生的,则减少直接访问数据库的总次数更为直接,只需编写WHERE逻辑以使用用户ID或其他内容(而不是当前的IN逻辑)过滤必要的用户电话号码。 This may even allow you to avoid the convoluted prepared statement syntax. 这甚至可以使您避免繁琐的预处理语句语法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM