我对如何在SQL中执行此操作感到不满.我有一张桌子:
| User_id | Question_ID | Answer_ID |
| 1 | 1 | 1 |
| 1 | 2 | 10 |
| 2 | 1 | 2 |
| 2 | 2 | 11 |
| 3 | 1 | 1 |
| 3 | 2 | 10 |
| 4 | 1 | 1 |
| 4 | 2 | 10 |
Run Code Online (Sandbox Code Playgroud)
它保存用户对特定问题的答案.一个问题可能有多个答案.用户无法回答两次相同的问题.(因此,每{User_id,Question_ID}只有一个Answer_ID)
我正在尝试找到这个查询的答案:对于特定的问题和答案ID(与同一问题相关),我想找到给定答案的用户给出的其他问题最常见的答案.
例如,对于上表:
For question_id = 1 -> For Answer_ID = 1 - (Question 2 - Answer ID 10)
For Answer_ID = 2 - (Question 2 - Answer ID 11)
Run Code Online (Sandbox Code Playgroud)
是否可以在一个查询中执行?它应该在一个查询中完成吗?我应该只使用存储过程或Java吗?
虽然 @rick-james 是对的,但我不确定当你不知道这样的查询通常是如何为 MySQL 编写的时,是否容易开始。
您需要查询来找出问题的最常见答案:
SELECT
question_id,
answer_id,
COUNT(*) as cnt
FROM user_answers
GROUP BY 1, 2
ORDER BY 1, 3 DESC
Run Code Online (Sandbox Code Playgroud)
这将返回一个表,其中对于每个 Question_id 我们按降序输出计数。
| 1 | 1 | 3 |
| 1 | 2 | 1 |
| 2 | 10 | 3 |
| 2 | 11 | 1 |
Run Code Online (Sandbox Code Playgroud)现在我们应该解决所谓的每组最大任务。问题是,在 MySQL 中,出于性能考虑,此类任务通常不是用纯 SQL 来解决,而是使用 hacks,这些 hacks 依赖于内部如何处理查询的知识。
在这种情况下,我们知道我们可以定义一个变量,然后迭代准备好的表,了解前一行,这使我们能够区分组中的第一行和其他行。
SELECT
question_id, answer_id, cnt,
IF(question_id=@q_id, NULL, @q_id:=question_id) as v
FROM (
SELECT
question_id, answer_id, COUNT(*) as cnt
FROM user_answers
GROUP BY 1, 2
ORDER BY 1, 3 DESC) cnts
JOIN (
SELECT @q_id:=-1
) as init;
Run Code Online (Sandbox Code Playgroud)
确保您已初始化该变量(并在初始化时尊重其数据类型,否则稍后可能会意外转换)。结果如下:
| 1 | 1 | 3 | 1 |
| 1 | 2 | 1 |(null)|
| 2 | 10 | 3 | 2 |
| 2 | 11 | 1 |(null)|
Run Code Online (Sandbox Code Playgroud)现在我们只需要过滤掉最后一列中带有 NULL 的行。由于实际上不需要该列,因此我们可以将相同的表达式移至 WHERE 子句中。cnt 列实际上也不需要,所以我们也可以跳过它:
SELECT
question_id, answer_id
FROM (
SELECT
question_id, answer_id
FROM user_answers
GROUP BY 1, 2
ORDER BY 1, COUNT(*) DESC) cnts
JOIN (
SELECT @q_id:=-1
) as init
WHERE IF(question_id=@q_id, NULL, @q_id:=question_id) IS NOT NULL;
Run Code Online (Sandbox Code Playgroud)最后值得一提的是,为了使查询高效,您应该拥有正确的索引。此查询需要一个以 (question_id,answer_id) 列开头的索引。由于您无论如何都需要一个 UNIQUE 索引,因此按以下顺序定义它是有意义的:(question_id、answer_id、user_id)。
CREATE TABLE user_answers (
user_id INTEGER,
question_id INTEGER,
answer_id INTEGER,
UNIQUE INDEX (question_id, answer_id, user_id)
) engine=InnoDB;
Run Code Online (Sandbox Code Playgroud)这是一个可以使用的sqlfiddle:http://sqlfiddle.com/#!9/bd12ad / 20。
| 归档时间: |
|
| 查看次数: |
210 次 |
| 最近记录: |