我的查询更好的MySQL语法

时间:2013-06-03 13:49:14

标签: mysql pdo

我有以下问题:

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

由于

贾斯汀

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

我会说实话。我真的不喜欢嵌套的select语句(select中的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不支持窗口功能。在我看来,一个非常合理的替换是子查询(通常是相关的)。这支持您的初始语法。