【问题标题】:Get data from multiple tables based on condition根据条件从多个表中获取数据
【发布时间】:2020-09-24 11:13:56
【问题描述】:

我需要从 3 个不同的 mysql 表中获取一些数据,如下所示。

 +-----------------------------------+      
 | Questions                         |      
 -------------------------------------      
 | id: int(8)                        |      
 | -- data we don't care about here  |      
 | question: TEXT                    |      
 +-----------------------------------+    

 +--------------------------+               
 |Answers                   |               
 +--------------------------+               
 | id: int(8)               |               
 | -- other data            |               
 | answer: TEXT             |               
 +--------------------------+    

 +-----------------------------------+      
 |Votes                              |      
 +-----------------------------------+      
 | id: int(8)                        |      
 | step: tinyint(1)                  |      
 | answerId: int(8)                  |      
 +-----------------------------------+      

我需要获得对每个问题的投票最多的答案以及该答案的票数。

我能想到的最好的查询是:

SELECT question, answer, count(votes.id) votesCount FROM questions INNER JOIN answers ON questions.id = answers.questionId INNER JOIN votes ON answers.id = votes.answerId;

但是这是错误的,因为它总是返回一个包含第一个问题、随机答案和总票数的结果。

【问题讨论】:

    标签: mysql sql count greatest-n-per-group window-functions


    【解决方案1】:

    您的直接问题是您的查询缺少group by 子句。所以它只返回一行,包括总票数和任意选择的问题和答案。

    如果您运行的是 MySQL 8.0,这可以通过聚合和窗口函数轻松完成:

    select question, answer, votescount
    from (
        select 
            q.question, 
            a.answer, 
            count(*) votescount,
            rank() over(partition by q.id order by count(*) desc) rn
        from questions q
        inner join answers a on q.id = a.questionid 
        inner join votes on a.id = v.answerid
        group by q.id, q.question, a.id, a.answer
    ) t
    where rn = 1
    

    在早期版本中,它有点复杂。一种选择是使用 having 子句过滤聚合结果集,该子句返回每个组的最高计数:

    select 
        q.question, 
        a.answer, 
        count(*) votescount,
        rank() over(partition by q.id order by count(*) desc) rn
    from questions q
    inner join answers a on q.id = a.questionid 
    inner join votes on a.id = v.answerid
    group by q.id, q.question, a.id, a.answer
    having count(*) = (
        select count(*)
        from answers a1
        inner join votes v1 a1.id = v1.answerid
        where a1.questionid = q.id
        group by a1.id
        order by count(*) desc
        limit 1
    )
    

    【讨论】:

    • 我使用的是最新版本的 mysql,所以这可以工作,但是有一个问题,如果一个问题的两个答案具有相同的票数,则返回两个结果而不是 1
    • @thelmuxkriovar:是的,rank() 就是这样做的。如果有平局,你想要哪个答案?
    • id最低的那个
    • @thelmuxkriovar:好的,所以row_number() over(partition by q.id order by count(*) desc, a.id)(我们可以使用相同的rank(),但row_number() 明确表示我们不想要联系)。
    • 行得通!非常感谢,您能否编辑您的答案以包含该内容?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    • 2017-10-26
    • 2021-11-29
    相关资源
    最近更新 更多