我会尝试通过在您的其他表上放置触发器来完全简化这一点,并且只需在您的 User_Fans 表中添加几列......您尝试从 Posts、PostLikes、PostComments、发表评论喜欢。
将记录添加到任何表时,只需更新您的 user_fans 表以将 1 添加到计数...无论如何,这将基于用户的密钥 ID 几乎是即时的。至于“LIKES”...类似,只有在某些东西被触发为“Like”的情况下,加1..然后您的查询将是对单个记录的直接数学运算,而不依赖于任何连接来计算a “加权”总值。随着您的表变得更大,查询也将变得更长,因为它们有更多的数据要涌入和聚合。您正在浏览每个 user_fan 记录,它本质上是从所有其他表中查询每条记录。
话虽如此,保持表格不变,我将重组如下......
SELECT
uf.user_name,
uf.user_id,
@pc := coalesce( PostSummary.PostCount, 000000 ) as PostCount,
@pl := coalesce( PostLikes.LikesCount, 000000 ) as PostLikes,
@cc := coalesce( CommentSummary.CommentsCount, 000000 ) as PostComments,
@cl := coalesce( CommentLikes.LikesCount, 000000 ) as CommentLikes,
@pc + @cc AS sum_post,
@pl + @cl AS sum_like,
@pCalc := (@pc + @cc) * 10 AS post_cal,
@lCalc := (@pl + @cl) * 5 AS like_cal,
@pCalc + @lCalc AS `total`
FROM
( select @pc := 0,
@pl := 0,
@cc := 0,
@cl := 0,
@pCalc := 0
@lCalc := 0 ) sqlvars,
user_fans uf
LEFT JOIN ( select user_id, COUNT(*) as PostCount
from post
group by user_id ) as PostSummary
ON uf.user_id = PostSummary.User_ID
LEFT JOIN ( select user_id, COUNT(*) as LikesCount
from post_likes
group by user_id ) as PostLikes
ON uf.user_id = PostLikes.User_ID
LEFT JOIN ( select user_id, COUNT(*) as CommentsCount
from post_comment
group by user_id ) as CommentSummary
ON uf.user_id = CommentSummary.User_ID
LEFT JOIN ( select user_id, COUNT(*) as LikesCount
from post_comment_likes
group by user_id ) as CommentLikes
ON uf.user_id = CommentLikes.User_ID
ORDER BY
`total` DESC
LIMIT 20
My variables are abbreviated as
"@pc" = PostCount
"@pl" = PostLikes
"@cc" = CommentCount
"@cl" = CommentLike
"@pCalc" = weighted calc of post and comment count * 10 weighted value
"@lCalc" = weighted calc of post and comment likes * 5 weighted value
对预查询的 LEFT JOIN 将这些查询运行一次,然后整个事物被连接,而不是作为每个记录的子查询被命中。通过使用 COALESCE(),如果 LEFT JOINed 表结果中没有这样的条目,您将不会被 NULL 值打乱计算,因此我将它们默认为 000000。
澄清您的问题
您可以将任何查询作为“AS AliasResult”。“As”也可用于简化任何长表名,以提高可读性。别名也可以使用同一个表但作为不同的别名来获取相似的内容,但目的不同。
select
MyAlias.SomeField
from
MySuperLongTableNameInDatabase MyAlias ...
select
c.LastName,
o.OrderAmount
from
customers c
join orders o
on c.customerID = o.customerID ...
select
PQ.SomeKey
from
( select ST.SomeKey
from SomeTable ST
where ST.SomeDate between X and Y ) as PQ
JOIN SomeOtherTable SOT
on PQ.SomeKey = SOT.SomeKey ...
现在,上面的第三个查询不需要(完整查询导致别名“PQ”代表“PreQuery”)。如果您想预先限制一组特定的其他复杂条件,并且在对许多其他表进行额外连接以获得所有最终结果之前想要一个较小的集合,则可以这样做。
由于“FROM”不必是一个实际的表,但它本身可以是一个查询,查询中使用的任何其他地方,它必须知道如何引用这个预查询结果集。
此外,在查询字段时,它们也可以是“As FinalColumnName”,以将结果简化到它们将被使用的位置。
从 ... 中选择 CONCAT(User.Salutation, User.LastName) 作为 CourtesyName
从 ... 中选择 Order.NonTaxable + Order.Taxable + ( Order.Taxable * Order.SalesTaxRate ) 作为 OrderTotalWithTax
“As” columnName 不需要是聚合,但最常见的是这种方式。
现在,关于 MySQL 变量...如果您正在执行存储过程,许多人会在过程的其余部分之前预先声明它们设置默认值。您可以通过设置并为结果提供“别名”引用来在查询中内联执行它们。执行这些变量时,选择将模拟始终返回一个 SINGLE RECORD 值的值。它几乎就像查询中使用的可更新的单个记录。您不需要应用任何特定的“加入”条件,因为它可能对查询中的其余表没有任何影响......本质上,创建一个笛卡尔结果,但一个记录对任何其他表将永远不会创建无论如何都重复,所以下游没有损坏。
select
...
from
( select @SomeVar := 0,
@SomeDate := curdate(),
@SomeString := "hello" ) as SQLVars
现在,sqlvars 是如何工作的。想想一个线性程序......一个命令在查询运行时以确切的顺序执行。然后将该值重新存储回“SQLVars”记录中,以备下次使用。但是,您不会将其引用为 SQLVars.SomeVar 或 SQLVars.SomeDate... 只是 @SomeVar := someNewValue。现在,当在查询中使用@var 时,它也会作为“As ColumnName”存储在结果集中。有时,这可能只是准备下一条记录的占位符计算值。然后每个值可直接用于下一行。因此,给定以下示例...
select
@SomeVar := SomeVar * 2 as FirstVal,
@SomeVar := SomeVar * 2 as SecondVal,
@SomeVar := SomeVar * 2 as ThirdVal
from
( select @SomeVar := 1 ) sqlvars,
AnotherTable
limit 3
Will result in 3 records with the values of
FirstVal SecondVal ThirdVal
2 4 8
16 32 64
128 256 512
注意@SomeVar 的值是如何在每列使用它时使用的......所以即使在同一条记录上,更新的值也可以立即用于下一列......也就是说,现在看看尝试建立一个模拟记录计数/ 每个客户的排名...
select
o.CustomerID,
o.OrderID
@SeqNo := if( @LastID = o.CustomerID, @SeqNo +1, 1 ) as CustomerSequence,
@LastID := o.CustomerID as PlaceHolderToSaveForNextRecordCompare
from
orders o,
( select @SeqNo := 0, @LastID := 0 ) sqlvars
order by
o.CustomerID
“Order By”子句强制首先按顺序返回结果。因此,这里将返回每个客户的记录。第一次通过,LastID 为 0,客户 ID 为...5。由于不同,它返回 1 作为@SeqNo,然后将该客户 ID 保存到下一条记录的 @LastID 字段中。现在,客户的下一条记录...最后一个 ID 是相同的,因此它采用 @SeqNo(现在 = 1),并将 1 加到 1 并成为同一客户的 #2... 继续前进.. .
至于如何更好地编写查询,请查看 MySQL 标签并查看一些重要的贡献者。研究问题和一些复杂的答案以及解决问题的工作原理。并不是说没有其他声誉得分较低的人刚刚起步并且完全胜任,但是您会发现谁给出了好的答案以及为什么。看看他们发布的答案历史。您阅读和遵循的越多,您就越能更好地处理编写更复杂的查询。