MySQL Join Group By 和 Group Concat

Posted

技术标签:

【中文标题】MySQL Join Group By 和 Group Concat【英文标题】:MySQL Join Group By and Group Concat 【发布时间】:2016-03-06 14:34:19 【问题描述】:

我正在跟踪连接到网络应用程序并在问题提要中留下问题的用户

用户

id  name
---------
1   Jim
2   Joe

因为用户可以从各种浏览器连接到应用程序并且有多个连接,所以我使用 Token 表来跟踪用户连接:

代币

id  userid
----------
1   1
2   1
3   2
4   2

然后用户提出问题:

问题

id  userid  pageno text
------------------------------------------------
1   1       1      'Whats going on here?'
2   1       2      'How are you?'
4   2       2      'Good and you?'

我的目标是输出以下内容

username  questions                               Questions Page 1        Questions Page 2
-----------------------------------------------------------------------------------
Jim       'Whats going on here?', 'How are you?'  'Whats going on here?'  'How are you?'
Joe       'Good and you?'                                                 'Good and you?'

现在我尝试直接查询用户表,但由于我的数据库中有很多用户,我需要查询令牌表而不是用户表以获得性能,然后按用户 ID 分组,因为一个用户可以获得许多令牌。

虽然现在我按用户 ID 分组,但我不确定如何对不同的问题进行分组。 查看查询:

SELECT  u.id, u.name, q.text
FROM token t
LEFT JOIN user as u ON t.userid = u.id
LEFT JOIN question as q ON t.userid = q.userid
GROUP BY t.userid

我的问题是我只得到了第一个问题,但我尝试将 concat 分组但没有运气。

忘记补充了,如果可以动态完成,那就太好了,因为页码会发生很大变化 你能帮忙吗? 谢谢

【问题讨论】:

【参考方案1】:

尝试了GROUP_CONCAT(DISTINCT q.text) as question FROM之后你得到了什么?

SELECT  u.id, u.name, GROUP_CONCAT(DISTINCT q.text) as question
FROM token t
LEFT JOIN user as u ON t.userid = u.id
LEFT JOIN question as q ON t.userid = q.userid
GROUP BY t.userid

【讨论】:

@Sdev 这在我的本地主机上运行良好。我试过了。 谢谢,这行得通,我已经编辑了帖子,因为我错过了按页面过滤的原始问题的一部分 @SDev Question Page 1 Question Page 2 是什么? 你想要Question Page 1 Question Page 2?作为列标题吗? 为了更清楚起见,我编辑了帖子。列标题并不那么重要,我无法实现的是查询每个页码的问题作为我查询的一部分【参考方案2】:

查询应该是这样的:

SELECT temp.*, (SELECT GROUP_CONCAT(q.text) FROM questions q WHERE q.pageno = temp.pageno) as Pagewiseqtn FROM (SELECT  u.id, u.name, GROUP_CONCAT(DISTINCT q.text) as question, q.pageno
FROM tokens t
LEFT JOIN users as u ON t.userid = u.id
LEFT JOIN questions as q ON t.userid = q.userid
GROUP BY t.userid) as temp

输出:

【讨论】:

谢谢 Rick,但我不确定这是正确的数据输出:在这个例子中,Jim 询问了“你好吗?”在第 2 页上,但它出现在乔所在的第二行 @SDev 我觉得可以通过编码实现【参考方案3】:

获得 OP 要求的确切结果的最容易理解和最简单的方法是将问题划分为多个子查询而不是单个查询。

我创建了多个中间VIEW 来获得最终结果。此外,使用中间 VIEW 而不是中间 TABLE 的好处是原始表中的任何更新也会导致 VIEW 中的结果更新

子查询 1:

CREATE VIEW q AS
    -> SELECT userid,  
    -> GROUP_CONCAT(text ORDER BY userid SEPARATOR ", ") AS questions
    -> FROM Questions
    -> GROUP BY userid;
    
SELECT * FROM q;
+--------+----------------------------------------+
| userid | questions                              |
+--------+----------------------------------------+
|      1 | 'How are you?', 'Whats going on here?' |
|      2 | 'Good and you?'                        |
+--------+----------------------------------------+

子查询 2:

CREATE VIEW q1 AS
    -> SELECT userid, text AS questions1
    -> FROM Questions
    -> WHERE pageno = 1;

SELECT * FROM q1;
+--------+------------------------+
| userid | questions1             |
+--------+------------------------+
|      1 | 'Whats going on here?' |
+--------+------------------------+

子查询 3:

CREATE VIEW q2 AS
    -> SELECT userid, text AS questions2
    -> FROM Questions
    -> WHERE pageno = 2;
    
SELECT * FROM q2;
+--------+-----------------+
| userid | questions2      |
+--------+-----------------+
|      1 | 'How are you?'  |
|      2 | 'Good and you?' |
+--------+-----------------+

子查询 4:

CREATE VIEW ql AS
    -> SELECT u.id, q.questions
    -> FROM Users AS u
    -> LEFT OUTER JOIN
    -> q ON u.id = q.userid;
    
SELECT * FROM ql;
+----+----------------------------------------+
| id | questions                              |
+----+----------------------------------------+
|  1 | 'How are you?', 'Whats going on here?' |
|  2 | 'Good and you?'                        |
+----+----------------------------------------+

子查询 5:

CREATE VIEW q1l AS
    -> SELECT u.id, q1.questions1
    -> FROM Users AS u
    -> LEFT OUTER JOIN
    -> q1 ON u.id = q1.userid;

SELECT * FROM q1l;
+----+------------------------+
| id | questions1             |
+----+------------------------+
|  1 | 'Whats going on here?' |
|  2 | NULL                   |
+----+------------------------+

子查询 6:

CREATE VIEW q2l AS
    -> SELECT u.id, q2.questions2
    -> FROM Users AS u
    -> LEFT OUTER JOIN
    -> q2 ON u.id = q2.userid;

SELECT * FROM q2l;
+----+-----------------+
| id | questions2      |
+----+-----------------+
|  1 | 'How are you?'  |
|  2 | 'Good and you?' |
+----+-----------------+

子查询 7:

CREATE VIEW vt AS
    -> SELECT u.name, 
    -> ql.questions, 
    -> q1l.questions1, 
    -> q2l.questions2
    -> FROM 
    -> Users AS u
    -> INNER JOIN
    -> ql ON u.id = ql.id
    -> INNER JOIN
    -> q1l ON ql.id = q1l.id
    -> INNER JOIN
    -> q2l ON q1l.id = q2l.id;
    
SELECT * FROM vt;
+------+----------------------------------------+------------------------+-----------------+
| name | questions                              | questions1             | questions2      |
+------+----------------------------------------+------------------------+-----------------+
| Jim  | 'How are you?', 'Whats going on here?' | 'Whats going on here?' | 'How are you?'  |
| Joe  | 'Good and you?'                        | NULL                   | 'Good and you?' |
+------+----------------------------------------+------------------------+-----------------+

最终查询:

CREATE VIEW v AS
    -> SELECT name AS username,
    -> COALESCE(questions, "") AS questions,
    -> COALESCE(questions1, "") AS "Questions Page 1",
    -> COALESCE(questions2, "") AS "Questions Page 2"
    -> FROM vt;
    
SELECT * FROM v;
+----------+----------------------------------------+------------------------+------------------+
| username | questions                              | Questions Page 1       | Questions Page 2 |
+----------+----------------------------------------+------------------------+------------------+
| Jim      | 'How are you?', 'Whats going on here?' | 'Whats going on here?' | 'How are you?'   |
| Joe      | 'Good and you?'                        |                        | 'Good and you?'  |
+----------+----------------------------------------+------------------------+------------------+

【讨论】:

以上是关于MySQL Join Group By 和 Group Concat的主要内容,如果未能解决你的问题,请参考以下文章

MySQL sum,用 group by 和 join 计数

如何在 JOIN MySQL 中进行 GROUP BY 和 COUNT(*)

使用中间表优化 MySQL Join 和 Group By

使用 MySQL 通过 JOIN 获取 GROUP BY 中的 SUM

带有 LEFT JOIN 和 GROUP BY 的 COUNT(*) 在 MySQL 中包含 NULL

使用 LEFT JOIN 的 MySQL 视图中的问题... GROUP BY