我有下一个表结构: 游戏 - 包含基本游戏信息(体育赛事), 投注 - 投注变化(团队获胜,团队b获胜等), 投票 - 用户选择投注变化。
下一个查询显示所有未开始游戏的所有最后投注变化的列表。 如果当前用户投票,列表中的某些投注也包含一些信息。
用于检测的插入选择下一个:1 - 用户是否已经投票进行此投注?,2 - 获得用户的选择(是\否),3 - 获得用户的投票金额。
SELECT bets.*, games.Time, games.TA, games.TB,
(SELECT COUNT(*) FROM votes WHERE BID=bets.BID AND UID=$UserID) AS Vt,
(SELECT YN FROM votes WHERE BID=bets.BID AND UID=$UserID) AS yn,
(SELECT Pt FROM votes WHERE BID=bets.BID AND UID=$UserID) AS Pt
FROM bets
LEFT JOIN games ON games.GID = bets.GID
WHERE games.Yes=0 AND bets.Dl=0
ORDER BY bets.Time DESC
我该如何优化它? 如何在一个查询中获得votes.YN和votes.Pt?
答案 0 :(得分:7)
您的left join
没用,因为您在第二个表中使用了一个值。因此,为了清楚起见,我会将其更改为inner join
。
此外,YN
和PT
的子查询没有聚合,因此它们似乎可以返回多行。我假设应该有sum()
。
然后,我将三个相关的子查询移动到from
子句中。这需要按bid
汇总:
SELECT bets.*, games.Time, games.TA, games.TB,
coalesce(v.vt, 0) as vt, coalesce(v.yn, 0) as yn, coalesce(v.pt, 0) as pt
FROM bets inner join
games
ON games.GID = bets.GID left join
(select bid, count(*) as vt, sum(yn) as yn, sum(pt) as pt
from votes v
where UID=$UserID
group by bid
) v
on v.bid = bets.bid
WHERE games.Yes=0 AND bets.Dl=0
ORDER BY bets.Time DESC;
编辑:
我要指出,这可能会也可能不会提供更好的性能(取决于where
子句的选择性等内容)。使用left outer join
保留bets
的所有行,可能会更好。
添加以下索引应修复查询的原始版本:votes(bid, uid)
。