Sql查询在每个类别中以最大投票数拉出前3条记录

时间:2010-11-19 19:24:50

标签: sql mysql greatest-n-per-group

将此查询放在一起需要一些帮助。我正在使用Mysql

我有两张桌子

视频 - 包含用户上传的视频

  • video_id
  • user_id
  • category_id

投票 - 包含任何用户对特定视频的投票

  • vote_id
  • video_id
  • user_id

我不想对查询中的类别进行硬编码 - 类别存储在具有category_id和category_name的类别表中

我基本上想要一个查询,为每个类别提取前三个视频(最多投票的视频)。

样本数据 - 视频表

video_id |  user_id  | category_id
   1          100          10
   2          101          10
   3          102          11
   4          103          11
   5          104          11
   6          105          11
   7          105          12

样本数据 - 投票表

vote_id  |  video_id |  user_id
  11           3          105
  12           3          102
  13           3          111
  14           3          121
  15           4          200
  16           4          201
  17           1          222

样本数据 - 类别表

category_id  |  category_name
   10               HipHop
   11               Rap
   12               Country

2 个答案:

答案 0 :(得分:1)

这是使用排名函数解决的问题类型。但是,由于MySQL还没有支持它们,因此它变得更加困难。在这个设计中,我假设video_id是视频表的主键。

Select video_id, user_id, category_id, vote_count, vote_rank
From    (
        Select VoteCounts.video_id, VoteCounts.user_id
            , VoteCounts.category_id, VoteCounts.vote_count
            , (
                Select Count(*) + 1
                From    (
                        Select V1.video_id, V1.user_id, V1.category_id
                            , Count(vote_id) As vote_count
                        From Videos As V1
                            Left Join Votes As V2
                                On V2.video_id = V1.video_id
                        Group By V1.video_id, V1.user_id, V1.category_id
                        )  As VoteCounts1
                Where VoteCounts1.category_id = VoteCounts.category_id
                    And (
                        VoteCounts1.vote_count > VoteCounts.vote_count
                        Or (VoteCounts1.vote_count = VoteCounts.vote_count
                            And VoteCounts1.video_id < VoteCounts.video_id )
                        )
                ) As vote_rank
        From    (
                Select V1.video_id, V1.user_id, V1.category_id
                    , Count(vote_id) As vote_count
                From Videos As V1
                    Left Join Votes As V2
                        On V2.video_id = V1.video_id
                Group By V1.video_id, V1.user_id, V1.category_id
                )  As VoteCounts
        ) As VoteRanks
Where VoteRanks.vote_rank <= 3

答案 1 :(得分:0)

我不知道MySQL,但是我会尝试在SQL Server中执行此操作,并根据有意义的结果进行一些调整。

select Category
        , Film
        , MAX(Votes) as Votes
    from (
        select TOP 3 c.category_name as Category
                , vd.video_id as Film
                , COUNT(vt.votes) as Votes
            from Category c
                inner join Video vd on vd.category_id = c.category_id
                inner join Votes vt on vt.video_id = vd.video_id
            where c.category_id = 10 -- HipHop
            group by c.category_name
                , vd.video_id
        union
        select TOP 3 c.category_name
                , vd.video_id
                , COUNT(vt.votes) as Votes
            from Category c
                inner join Video vd on vd.category_id = c.category_id
                inner join Votes vt on vt.video_id = vd.video_id
            where c.category_id = 11 -- Rap
            group by c.category_name
                , vd.video_id
        -- You need as much UNION as there are categories.
    ) Top3VotesPerCategory
    group by Category
        , Film

根据你是否接受电影的投票,人们可以在电影中注册反对票,这并不意味着他推荐这部影片。如果你确实支持这样的功能,那么你可能想要考虑一个条件SUM()而不是COUNT()的投票数,这样就会考虑负面投票,并会降低其整体积分关于投票。