[英]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: 基本上我有两个表:
user_feeds
is the table that holds the "feeds" data. user_feeds
是保存“提要”数据的表。
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
). 为了使查询更短并且可能更易于阅读,我建议使用表别名(
a
, b
, c
, d
)。 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.