一个复杂的MySQL JOIN SELECT

时间:2014-11-14 10:21:06

标签: mysql sql

在开始之前,请允许我说明:

  1. 我没有创建表格。
  2. 无法更改表格。
  3. 问题按“原样”描述。没有任何重要意义。
  4. 考虑2个表:

    CREATE TABLE `answers` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `question_id` int(11) NOT NULL DEFAULT '0',
      `user_id` int(11) NOT NULL DEFAULT '0',
      `text` TEXT,
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8
    
    CREATE TABLE `rating` (
      `answer_id` int(11) NOT NULL DEFAULT '0',
      `direction` varchar(10) NOT NULL DEFAULT '',
      `user_id` int(11) NOT NULL DEFAULT '0',
      UNIQUE KEY (`answer_id`, `user_id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8
    

    现在是烦人的部分。答案表是不言自明的,所以我只举几个评级行的例子

    +-------------+-------------+-----------+
    |  answer_id  |  direction  |  user_id  |
    +-------------+-------------+-----------+
    |      1      |    up       |    23     |
    |      1      |    down     |    26     |
    |      2      |    up       |    32     |
    |      2      |    up       |    42     |
    |      2      |    up       |    22     |
    |      2      |    down     |    23     |
    |      3      |    up       |    45     |
    |      3      |    up       |    22     |
    +-------------+-------------+-----------+
    

    现在我要做的是选择所有answers,每个答案的对应“向上”COUNT,“向下”COUNT,以及“向上”和“向下”COUNT之间的差异。

    假设upcount是“向上”的总数,downcount是“向下”的总数,而score是他们的差异,例如:

    SELECT [SOMETHING?] AS `upcount`,
    [SOMETHING?] AS `downcount`,
    (`upcount`-`downcount`) AS `score`,
    ans.* FROM answers AS ans LEFT JOIN rating AS r ON ans.id=r.answer_id
    [...] ORDER BY `score`, `upcount`
    

    当然,我强烈怀疑该解决方案会像我给出的示例一样任何。我只是想说明每条记录应该有upcount,downcount,score和所有答案字段。

    非常感谢非常感谢,谢谢!

    PS。我知道如果上下是2个单独的列并且有数值,我可以很容易地使用SUM()。但就像我说的,我没有创建这个表;)

1 个答案:

答案 0 :(得分:1)

可能是一个简单的GROUP BY子句连接,但总结基于IF语句,而不是计数: -

SELECT a.id, 
        SUM(IF(b.direction='up', 1, 0)) AS upcount, 
        SUM(IF(b.direction='down', 1, 0)) AS downcount,
        SUM(IF(b.direction='up', 1, -1)) AS score
FROM answers a
LEFT OUTER JOIN rating b
ON a.id = b.answer_id
GROUP BY a.id
ORDER BY score, upcount

编辑 - 避免使用SUM的IF语句的另一种可能的解决方案是加入评级表两次并使用COUNT(DISTINCT)。由于user_id对于答案是唯一的,因此我们可以计算不同的用户ID。下方是获得整体得分有点麻烦。

SELECT a.id, 
        COUNT(DISTINCT b1.user_id) AS upcount, 
        COUNT(DISTINCT b2.user_id) AS downcount, 
        (COUNT(DISTINCT b1.user_id) - COUNT(DISTINCT b2.user_id)) AS score
FROM answers a
LEFT OUTER JOIN rating b1
ON a.id = b1.answer_id
AND b1.direction='up'
LEFT OUTER JOIN rating b2
ON a.id = b2.answer_id
AND b2.direction='down'
GROUP BY a.id
ORDER BY score, upcount