我有2个查询可以单独运行。鉴于它们相似,我想将它们合并为一个高性能查询。看起来很简单,因为where子句是相似的。但是sum,count和min函数都适用于不同的行并妨碍它们。
上下文:
问题:
如何重组下面的查询以组合约束?必须有一种方法可以在特定日期之后从特定位置开始获得分数列表。唯一的复杂因素是获得用户B的第一个得分日期,并且只有在用户A到期日之后才向其提供推荐积分。
select scoring.userId, scoring.points + referring.points as leaderPoints
from (
select userId, sum(ratingPoints) as points
from scores s, locations l
where s.locationId = l.locationId and
l.locationArea = 'Massachusetts' and
l.locationCountry = 'United States' and
s.scoreDateTime > '2016-04-16 18:50:53.154' and
s.userId != 0
group by s.userId
) as scoring
join (
select u1.userId, count(*) * 20 as points
from users u0
join users u1 on u0.userId = u1.userId
join users u2 on u2.referredByEmail = u1.emailAddress
join scores s on u2.userId = s.userId
join locations l on s.locationId = l.locationId
where l.locationArea = 'Massachusetts' and
l.locationCountry = 'United States' and
scoreDateTime = (
select min(scoreDateTime)
from scores
where userId = u2.userId
) and
scoreDateTime >= '2016-04-16 18:50:53.154'
group by u1.userId
) as referring on scoring.userId = referring.userId
order by leaderPoints desc
limit 10;
答案 0 :(得分:0)
这是未经测试的代码,但它应该可以解决问题。 Cross Apply是为了提高可读性......它会损害性能,但这似乎不是一个特别针对流程的查询,所以我会保留它。
如果您有任何疑问,请试试看。
SELECT U.UserID,
ISNULL(SUM(CASE WHEN S.UserID IS NULL THEN 0 ELSE S.ratingPoints END), 0) AS [Rating Points],
ISNULL(SUM(CASE WHEN SS.userID IS NULL THEN 0 ELSE 20 END), 0) AS [Referral Points]
FROM Users U
LEFT OUTER JOIN scores S
ON S.userID = U.userID
AND S.scoreDateTime >= '2016-04-16 18:50:53.154'
LEFT OUTER JOIN locations L
ON S.locationID = L.locationID
AND L.locationArea = 'Massachusetts'
AND L.LocationCountry = 'United States'
LEFT OUTER JOIN Users U2
ON U2.referredByEmail = U.emailAddress
LEFT OUTER JOIN scores SS
ON SS.userID = U2.userID
LEFT OUTER JOIN locations LL
ON SS.locationID = LL.locationID
AND LL.locationArea = 'Massachusetts'
AND LL.locationCountry = 'United States'
AND SS.scoreDateTime >= '2016-04-16 18:50:53.154'
AND SS.scoreDateTime =
(
SELECT MIN(scoreDateTime)
FROM scores
where userID = U2.userID
)
GROUP BY U.userID
编辑:
删除交叉申请的修改后的答案
答案 1 :(得分:0)
感谢Stan Shaw,但我无法让您的查询在MySQL上运行以测试结果。但是,我确实注意到我的原始查询未涵盖的特殊情况。用户可以从他们自己未提交分数的区域获得参考点。只要新用户在该区域得分,他们就会获得参考点。
这是我正在使用的最终查询。我无法以一种看似高效的方式将副本合并到where子句中。
select userId, sum(points) as leaderPoints
from (
select s.userId, sum(s.ratingPoints) as points
from scores s, locations l
where s.locationId = l.locationId and
l.locationArea = 'Georgia' and
l.locationCountry = 'United States' and
s.scoreDateTime >= '2016-04-05 03:00:00.000' and
s.userId != 1
group by userId
union
select u1.userId, 20 as points
from users u0, users u1, users u2, scores s, locations l
where u0.userId = u1.userId and
u2.referredByEmail = u1.emailAddress and
u2.userId = s.userId and
s.locationId = l.locationId and
l.locationArea = 'Georgia' and
l.locationCountry = 'United States' and
scoreDateTime >= '2016-04-05 03:00:00.000' and
scoreDateTime = (
select min(scoreDateTime)
from scores
where userId = u2.userId
)
) as pointsEarned
group by userId
order by leaderPoints desc
limit 10
order by leaderPoints desc
limit 100;