Select 每个给定用户 post 的 SO 声誉

Select SO reputation per post for a given user

我目前正在为 SEDE 进行 SQL 查询,它从 Stack Overflow 中选择一个用户的所有 post 并显示每个 post 的信誉度生成。

我想不通的是如何计算所有赞成票反对票接受票 每个 post,然后计算每个 post 的整体声望增益。

所以我想按 Post id 分组显示 Total score 并显示整体获得了多少声望。

每次投票产生的声望可以在这里看到:

+-----------+----------+--------+
| Post type | Question | Answer |
+-----------+----------+--------+
| Upvote    |    5     |   10   |
+-----------+----------+--------+
| Downvote  |    2     |    2   |
+-----------+----------+--------+
| Accept    |    5     |   15   |
+-----------+----------+--------+

可以找到我的目标数据库模式 here

到目前为止,我的查询如下所示:

select 
  p.Id as 'Post id', 
  pt.Name as 'Post type',
  p.Score as 'Total score',
  (
    case vt.Id
      when 1 then 'Accept'
      when 2 then 'Upvote'
      else 'Downvote'
      end
  ) as 'Reputation type'
from 
  Posts p
join 
  Votes v
on
  v.PostId = p.Id
join 
  VoteTypes vt
on 
  vt.Id = v.VoteTypeId
join
  PostTypes pt
on 
  pt.Id = p.PostTypeId
where
  p.OwnerUserId = ##UserId##
and 
  vt.Id in (1, 2, 3)
order by
  p.Score,
  vt.Id
asc

它产生的输出看起来像这样:

我尝试按 Vote type id:

分组
group by  
  vt.id

这样我至少可以找出每个人 post 累积了多少不同的选票,方法是使用以下方法:

select
  ....
  count(vt.id)

但随后我收到无法解析 Posts.Id 列的错误消息:

可以找到当前运行可用但不完整的查询here(您必须输入您的用户ID才能运行 )

您可以尝试这样的操作:

 select 
 p.Id as 'Post id', 
 pt.Name as 'Post type',
 SUM
 (
    case vt.Id
    when 1 then 15
    when 2 then 10
    else -2
    end
    ) as 'Total Score'
    .....
   GROUP BY P.Id, Pt.Name
   ORDER BY....

每个 post 的声誉比这要复杂一些。
除了Up/Down/Accept票之外,还有:

  1. 赏金,
  2. 代表上限,
  3. 用户的代表次数(没有用户的代表次数不能少于 1(通常))。
  4. 社区 Wiki。
  5. 垃圾邮件或滥用标记。
  6. 问题的点赞数因网站而异。
  7. 许多 post 根本没有投票,因此 SQL 需要反映这一点。 (左连接、COALESCE 等)
  8. 您是否将 post(2 分代表)的批准建议修改算作?
  9. 可能还有什么我忘记了。


根据您的实际需求,您可以考虑使用 this API method instead(然后按 post_id 对结果进行分组)。

无论如何,here's your query tuned up a bit:

SELECT      p.Id      AS [Post Link]
            , pt.Name AS 'Post type'
            , p.Score AS 'Total score'
            , COALESCE (vtStats.AcceptRep, 0)   AS [Accept Rep]
            , COALESCE (vtStats.numUpvotes, 0)  *  (
                CASE  p.PostTypeId
                    WHEN  1  THEN  5  -- Questions on most sites
                    WHEN  2  THEN 10  -- Answers
                    ELSE  1  -- Should not happen, but don't zero out
                END
            ) AS [Up Vt Rep]
            , COALESCE (vtStats.DwnVtRep, 0)    AS [Dwn Vt Rep]
FROM        Posts p
LEFT JOIN   (
    SELECT      v.PostId
                , SUM (CASE v.VoteTypeId    WHEN 1  THEN 15  ELSE 0  END)   AS AcceptRep
                , SUM (CASE v.VoteTypeId    WHEN 3  THEN -2  ELSE 0  END)   AS DwnVtRep
                , SUM (CASE v.VoteTypeId    WHEN 2  THEN  1  ELSE 0  END)   AS numUpvotes -- Needs special handling
    FROM        Votes v
    WHERE       v.VoteTypeId IN (1, 2, 3 )
    GROUP BY    v.PostId
)
AS vtStats  ON  vtStats.PostId = p.Id
INNER JOIN  Posttypes pt    ON pt.Id = p.PostTypeId
WHERE       p.OwnerUserId = ##UserId:Int##
ORDER  BY   p.Score DESC
            , [Accept Rep] DESC
            , pt.Name