我是Rails开发人员,我是编写SQL脚本的新手。我有users
,portfolios
,views
,favorites
和endorsements
表格。 users
有许多portfolios
个endorsements.
投资组合has many
次观看, many
次收藏and many
代言。
这是我写的脚本
top_users = User.find_by_sql(
"SELECT users.*,
COUNT(portfolios.id) +
COUNT(views.id) +
COUNT(favorites.id) +
COUNT(case when endorsements.portfolio_id = portfolios.id AND portfolios.user_id = users.id then 1 else 0 end) +
COUNT(case when endorsements.user_id = users.id then 1 else 0 end)
AS total
FROM users
LEFT OUTER JOIN portfolios ON portfolios.user_id = users.id
LEFT OUTER JOIN views ON views.subject_id = portfolios.id AND portfolios.user_id = users.id
LEFT OUTER JOIN favorites ON favorites.subject_id = portfolios.id AND portfolios.user_id = users.id
LEFT OUTER JOIN endorsements ON endorsements.portfolio_id = portfolios.id AND portfolios.user_id = users.id OR endorsements.user_id = users.id
GROUP BY users.id
ORDER BY total DESC LIMIT 8"
)
total
计数并不完全符合我的预期,因为每个portfolio
值50
分,view
为2
分,favorite
为值10
分,endorsement
值2
分。
假设我们有3个用户
user | COUNT 1 | COUNT 2 | COUNT 3 | COUNT 4 | COUNT 5
-------------------------------------------------------
1 | 0 | 0 | 0 | 0 | 10
2 | 2 | 2 | 2 | 2 | 0
3 | 5 | 0 | 0 | 0 | 0
使用我的脚本,结果按user 1
,user 2
,然后users 3
的顺序排列。但是,根据积分系统,它应该按user 3
,user 2
然后user 1
的顺序出现,因为user 3
总积分为250
,{{1总计为users 2
,128
为user 1
,这是我期望的顺序。我试过这个:
20
我尝试了上面的脚本,但对我不起作用。任何想法或帮助将不胜感激。同样,我对原始SQL脚本非常新。
已更新 当LEFT INNTER JOIN多表时,我最终这样做是为了避免重复计算问题。
top_users = User.find_by_sql(
"SELECT users.*,
COUNT(portfolios.id) * 50 +
COUNT(views.id) * 2 +
COUNT(favorites.id) * 10 +
COUNT(case when endorsements.portfolio_id = portfolios.id AND portfolios.user_id = users.id then 1 else 0 end) * 2 +
COUNT(case when endorsements.user_id = users.id then 1 else 0 end) * 2
AS total
FROM users
LEFT OUTER JOIN portfolios ON portfolios.user_id = users.id
LEFT OUTER JOIN views ON views.subject_id = portfolios.id AND portfolios.user_id = users.id
LEFT OUTER JOIN favorites ON favorites.subject_id = portfolios.id AND portfolios.user_id = users.id
LEFT OUTER JOIN endorsements ON endorsements.portfolio_id = portfolios.id AND portfolios.user_id = users.id OR endorsements.user_id = users.id
GROUP BY users.id
ORDER BY total DESC LIMIT 8"
)
因为我不熟悉SQL脚本,因为我是一个非常初学者。上面更新的代码解决了我的问题,但我想知道如果我这样做,糟糕表现会如何。感谢您提供任何意见。
答案 0 :(得分:1)
首先,除非你的'users'表只有一列,否则这会破坏以下规则:当你在select子句中有聚合函数时,每个未传递给聚合函数的列都必须在你的group by clause。
其次我不认为COUNT()函数中的case语句是有意义的。它们与您的加入中的语句相同。你应该能够计算endoresements.Id和Portfolios.id,我想。我可能会对你正在寻找的东西有点模糊。另外,什么是subject_id?是一个id字段,用于确定认可是属于用户还是投资组合? 投资组合是否同时具有user_id和portfolio_id,或者它是一个还是另一个但不是两者都有?
答案 1 :(得分:1)
经过几次阅读后,我想我得到了你说的话。试试这个。
SELECT users.id
,COUNT(portfolios.id) * 50 +
COUNT(VIEWS.id) * 2 +
COUNT(favorites.id) * 10 +
COUNT(e1.id) * 2 +
COUNT(e2.id) * 2
AS total
FROM users
LEFT JOIN portfolios
ON portfolios.user_id = users.id
LEFT JOIN VIEWS
ON VIEWS.subject_id = portfolios.id
LEFT JOIN favorites
ON favorites.subject_id = portfolios.id
LEFT JOIN endorsements e1
ON e1.portfolio_id = portfolios.id
LEFT JOIN endorsements e2
ON e2.user_id = users.id
GROUP BY users.id
ORDER BY total DESC LIMIT 8
我认为与用户或投资组合相关的认可。我不知道你的价值观在你的牌桌上是什么样的,但理论上,由于认可与用户或投资组合有关,但投资组合总是与用户有关,因此加入两者都不是绝对必要的。 user_id或portfolio_id。在这种情况下,它会发现将用户表加入到e1的批注中,并将投资组合表作为e2加入到代言中,然后添加它们。
答案 2 :(得分:1)
如果GROUP BY
查询中有多个外部联接,则必须be careful of double-counting。因此,我会将COUNT(portfolios.id)
更改为COUNT(DISTINCT portfolios.id)
等。这也应该消除了对CASE
语句的需求。获得这些计数后,您可以按照您在问题中所说的(* 2
或* 50
或您喜欢的任何内容)乘以其得分值。