我有SQL的这个问题,我无法弄明白。 想象一下,我有3个表如下
Names
Nameid name
1 Starbucks Coffee
2 Johns Restaurant
3 Davids Restaurant
user_likes
userid Nameid
1 1
2 1
2 3
user_visited
userid Nameid
1 2
我想找到数量最多(喜欢+访问过)的地方。我还想选择所有地方,而不仅仅是那些被喜欢或访问过的地方
我做:
SELECT n.nameid, n.name , COUNT(f.nameid) AS freq
FROM names AS n
LEFT JOIN user_likes ON n.nameid=user_likes.nameid
LEFT JOIN user_visited ON n.nameid=user_visited.nameid
ORDER BY freq DESC
但它并没有给我总频率。问题是,如果一个地方既被访问过也喜欢过,它只被计算一次,而我希望它被计算两次。 有什么建议吗?
答案 0 :(得分:2)
SELECT n.name, t.nameid, COUNT(t.nameid) AS freq
FROM Names n
JOIN (
SELECT nameid FROM user_likes
UNION ALL
SELECT nameid FROM user_visited
) t
ON n.nameid = t.nameid
GROUP BY t.nameid ORDER BY freq DESC
答案 1 :(得分:2)
我做了一个快速测试,虽然我更喜欢Serge的解决方案,但这一点似乎表现得更快,因为加入的项目数量会更少:
SELECT n.nameId, n.name, coalesce(sum(likesCount), 0) totalCount FROM NAMES n
LEFT JOIN (
SELECT nameId, count(*) likesCount FROM user_likes
GROUP BY nameId
UNION ALL
SELECT nameId, count(*) visitsCount FROM user_visited
GROUP BY nameId
) s ON n.nameId = s.nameId
GROUP BY n.nameId
ORDER BY totalCount DESC
我假设以下索引:
alter table names add index(nameid);
alter table user_likes add index(nameid);
alter table user_visited add index(nameid);
OP可能会将两个查询的效率与实际数据进行比较并提供反馈。
答案 2 :(得分:0)
Mosty,你对coalesce()的使用给了我一个想法,我想出了这个:
SELECT n.nameid, n.name ,
SUM((IFNULL(user_likes.userid,0)>0)+(IFNULL(user_visited.userid,0)>0) ) AS freq
FROM names AS n LEFT JOIN user_likes ON n.nameid=user_likes.nameid LEFT JOIN
user_visited ON n.nameid=user_visited.nameid ORDER BY freq DESC
因为我的例子是我的问题的简化(我必须将两个以上的表连接到主表)我不愿意在SELECT中使用SELECT,因为我知道它不是很有效。您是否看到我的解决方案存在任何根本问题?