我在 stackoverflow 上找不到问题的答案。我有一个跨越 3 个表的查询:
newsitem
+------+----------+----------+----------+--------+----------+
| Guid | Supplier | LastEdit | ShowDate | Title | Contents |
+------+----------+----------+----------+--------+----------+
newsrating
+----+----------+--------+--------+
| Id | NewsGuid | UserId | Rating |
+----+----------+--------+--------+
usernews
+----+----------+--------+----------+
| Id | NewsGuid | UserId | ReadDate |
+----+----------+--------+----------+
Newsitem 显然包含新闻站点,新闻评级包含用户对新闻站点的评分,而 usernews 包含用户阅读新闻站点的日期。
在我的查询中,我想获取每个新闻网站,包括该新闻网站的评分数量和平均评分,以及当前用户阅读该新闻网站的次数。
到目前为止我所拥有的是:
select newsitem.guid, supplier, count(newsrating.id) as numberofratings,
avg(newsrating.rating) as rating,
count(case usernews.UserId when 3 then 1 else null end) as numberofreads from newsitem
left join newsrating on newsitem.guid = newsrating.newsguid
left join usernews on newsitem.guid = usernews.newsguid
group by newsitem.guid
我在这里创建了一个sql fiddle :http://sqlfiddle.com/#!9/c8add/8
两个 count() 调用都没有返回我想要的数字。 numberof ratings 应返回该新闻站点的评分总数(所有用户)。 numberofreads 应返回该新闻网站当前用户的阅读次数。
因此,对于 userid = 3 的当前用户,guid 为 d104c330-c319-40e8-8be3-a7c4f549d35c 的 newsitem 应该有 2 个评分和 3 个读取。
我尝试过条件计数和求和,但尚未成功。如何才能做到这一点?
最佳答案
我看到的主要问题是您将两个表连接在一起,这意味着您将有效地乘以两个数字,这就是您的计数不正确的原因。例如,如果 Newsitem 已被用户阅读 3 次并被 8 位用户评分,那么您最终将获得 24 行,因此看起来它已被评分 24 次。您可以将 DISTINCT
添加到您的 COUNT
评分 ID 中,这样就可以解决该问题。平均值应该不受影响,因为 1 和 2 的平均值与 1, 1, 2, & 2 的平均值相同(例如)。
然后,您可以通过将用户 ID 添加到 JOIN
条件(因为它是 OUTER JOIN
它不应该导致任何结果丢失)而不是在为您的 COUNT
编写一个 CASE
语句,然后您可以对 Usernews 中的不同 id 值执行 COUNT
操作。结果查询将是:
SELECT
I.guid,
I.supplier,
COUNT(DISTINCT R.id) AS number_of_ratings,
AVG(R.rating) AS avg_rating,
COUNT(DISTINCT UN.id) AS number_of_reads
FROM
NewsItem I
LEFT OUTER JOIN NewsRating R ON R.newsguid = I.guid
LEFT OUTER JOIN UserNews UN ON
UN.newsguid = I.guid AND
UN.userid = @userid
GROUP BY
I.guid,
I.supplier
虽然这应该可行,但您可能会从子查询中获得更好的结果,因为上面需要分解结果然后聚合它们,这可能是不必要的。另外,有些人可能会发现下面的内容更清晰一些。
SELECT
I.guid,
I.supplier,
R.number_of_ratings,
R.avg_rating,
COUNT(*) AS number_of_reads
FROM
NewsItem I
LEFT OUTER JOIN
(
SELECT
newsguid,
COUNT(*) AS number_of_ratings,
AVG(rating) AS avg_rating
FROM
NewsRating
GROUP BY
newsguid
) R ON R.newsguid = I.guid
LEFT OUTER JOIN UserNews UN ON UN.newsguid = I.guid AND UN.userid = @userid
GROUP BY
I.guid,
I.supplier,
R.number_of_ratings,
R.avg_rating
关于mysql - 带连接的 Sql 条件计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34657457/