0

嗨我有以下查询:

SELECT PAS_User.user_user_id, 
PAS_User.user_city, 
PAS_User.user_company, 
PAS_User.user_country, 
PAS_User.user_account_type, 
PAS_User.user_account_premium, 
PAS_User.user_sign_up_date, 
PAS_User.user_first_name, 
PAS_User.user_last_name, 
PAS_User.user_avatar_url, 
PAS_User.user_cover_image_url, 
PAS_User.user_bio, 
PAS_User.user_sector, 
PAS_User.user_job_type, 
(SELECT COUNT(*) FROM `PAS_Follow` WHERE `folw_follower_user_id`=:sid) AS user_following_count,
(SELECT COUNT(*) FROM `PAS_Follow` WHERE `folw_followed_user_id`=:sid) AS user_followed_count,
(SELECT COUNT(*) FROM `PAS_Post` WHERE `post_user_id`=:sid) AS user_post_count, 
(SELECT COUNT(*) FROM `PAS_Follow` WHERE `folw_follower_user_id`=:sid AND `folw_followed_user_id`=:cid) AS user_this_user_is_following, 
(SELECT COUNT(*) FROM `PAS_Follow` WHERE `folw_followed_user_id`=:cid AND `folw_follower_user_id`=:sid) AS user_this_user_is_followed 
FROM PAS_User 
WHERE `PAS_User`.`user_user_id`=:sid

它旨在从其他表中获取个人资料页面的计数以及 :sid = 1 和 :cid = 2 的基本用户详细信息。

问题是,有没有更好的方法以更小的查询或更清洁的方式实现这一目标?

使用的表是

PAS_User , PAS_Follow & PAS_Post

谢谢

贾斯汀

4

2 回答 2

1

您应该对所有这些计数器字段进行非规范化,并且仅在用户发布内容或按下关注按钮时更新它们。如果您的网站获得实际活跃用户,您当前的查询将在可预见的将来炸毁您的数据库服务器。

于 2013-06-03T13:53:37.617 回答
0

我会诚实的。我不太喜欢嵌套select语句(selectwithin select)。但是,在您的情况下,替代方案可能更丑陋并且容易出现性能错误。诱惑是做类似的事情:

select . . .
from PAS_User u left outer join
     (select folw_foller_user_id, count(*) as user_following_count
      from PAS_Follow pf
      group by folw_foller_user_id
     ) pf
     on pf.folw_foller_user_id = u.user_user_id left outer join
     . . .

美好的。但这将比您的原始查询执行得更差,因为user_user_id. 要解决此问题,您将在子查询中重复该条件:

select . . .
from PAS_User u left outer join
     (select folw_foller_user_id, count(*) as user_following_count
      from PAS_Follow pf
      where folw_foller_user_id = :sid
      group by folw_foller_user_id
     ) pf
     on pf.folw_foller_user_id = u.user_user_id left outer join
     . . .

甚至:

select . . .
from PAS_User u cross join
     (select count(*) as user_following_count
      from PAS_Follow pf
      where folw_foller_user_id = :sid
     ) pf
     on pf.folw_foller_user_id = u.user_user_id left outer join
     . . .

我什至可能会争辩说,在一个子查询中重复条件会很好。我不能为五个子查询提出这个论点。

为了清楚起见,最好的语法是用户窗口函数:

select . . .
       count(*) over (partition by folw_fllower_user_id) as user_following_count,
       . . .

唉,MySQL 不支持窗口函数。在我看来,一个非常合理的替代品是子查询(通常是相关的)。这支持您的初始语法。

于 2013-06-03T14:31:42.763 回答