如何在MySQL中基于外键将两个表中的行合并为一个表?

问题描述

我在MysqL中有2个表,如下所示:

+------+-------+------------------+
| ID   | Q_ID  |Question          |
+------+-------+------------------+
|1     | 1     |Colors in Rainbow |
|2     | 2     |Colors in Tree    |
+------+-------+------------------+


+------+-------+--------+
| ID   | Q_ID  |Answer  |
+------+-------+--------+
|1     | 1     |Violet  |
|2     | 1     |Blue    |
|3     | 1     |Yellow  |
|4     | 2     |brown   |
|5     | 2     |Orange  |
|6     | 2     |Green   |
+------+-------+--------+

Q_Id 链接两个表的字段。 每个Q_id都有恰好3个选项作为答案。

现在,我想在MysqL中编写一个查询,该查询给出下表作为输出

+------+--------------------+----------+----------+----------+
| Q_ID | Question           |Answer 1  |Answer 2  |Answer 3  |
+------+--------------------+----------+----------+----------+
| 1    | Colors in Rainbow  |Violet    |Blue      |Yellow    |
| 2    | Colors in Tree     |brown     |Orange    |Green     |
+------+--------------------+----------+----------+----------+

我该怎么做??

解决方法

如果是所有情况,则可以在此处使用简单的CASE WHENMAX组合。

Working Solution

SELECT Q_ID,QUESTION,MAX(CASE WHEN MOD(ID,3)=1 THEN ANSWER END) AS ANS1,3)=2 THEN ANSWER END) AS ANS2,3)=0 THEN ANSWER END) AS ANS3
 FROM
(WITH TAB1 AS 
(
SELECT 1 AS ID,1 AS Q_ID,'Colors in Rainbow' AS QUESTION UNION ALL
SELECT 2 AS ID,2 AS Q_ID,'Colors in Tree'    AS QUESTION
),TAB2 AS (
SELECT 1 AS ID,'Violet' AS ANSWER UNION ALL
SELECT 2 AS ID,'Blue  ' AS ANSWER UNION ALL
SELECT 3 AS ID,'Yellow' AS ANSWER UNION ALL
SELECT 4 AS ID,'Brown ' AS ANSWER UNION ALL
SELECT 5 AS ID,'Orange' AS ANSWER UNION ALL
SELECT 6 AS ID,'Green ' AS ANSWER 
)
SELECT TAB2.ID,TAB1.Q_ID,TAB1.QUESTION,TAB2.ANSWER FROM TAB1 INNER JOIN TAB2 ON TAB2.Q_ID=TAB1.Q_ID 
) A
GROUP BY Q_ID,QUESTION

编辑:

正如stickybit所说,我的第一个答案有一个缺陷。为了消除此缺陷,我使用了ROW_NUMBER。该编辑是根据stickybit的指导进行的。感谢您的建议。 (窗口功能仅适用于mysql 8.0或更高版本。)

Source

SELECT Q_ID,MAX(CASE WHEN MOD(RN,'Violet' AS ANSWER UNION ALL
SELECT 4 AS ID,'Blue' AS ANSWER UNION ALL
SELECT 7 AS ID,'Yellow' AS ANSWER UNION ALL
SELECT 10 AS ID,'Brown' AS ANSWER UNION ALL
SELECT 13 AS ID,'Orange' AS ANSWER UNION ALL
SELECT 16 AS ID,'Green' AS ANSWER 
)
SELECT row_number() OVER (PARTITION BY TAB1.Q_ID ORDER BY TAB2.ID) as rn,TAB2.ID,QUESTION

enter image description here

,

一种方法是对LIMITOFFSET使用子查询。

SELECT t1.q_id,(SELECT t2.answer
               FROM elbat2 t2
               WHERE t2.q_id = t1.q_id
               ORDER BY t2.id
               LIMIT 1
               OFFSET 0) answer1,(SELECT t2.answer
               FROM elbat2 t2
               WHERE t2.q_id = t1.q_id
               ORDER BY t2.id
               LIMIT 1
               OFFSET 1) answer2,(SELECT t2.answer
               FROM elbat2 t2
               WHERE t2.q_id = t1.q_id
               ORDER BY t2.id
               LIMIT 1
               OFFSET 2) answer3
       FROM elbat1 t1;

db<>fiddle
请注意,您需要在此处ORDER BY的某些列,否则将无法保证顺序,这可能导致某些答案出现多次或根本不出现。

,

使用表group_concat()中的answers按照正确的顺序排列答案,然后加入questions,在其中使用substring_index()进行拆分:

select q.q_id,q.question,substring_index(all_answers,',1) Answer1,substring_index(substring_index(all_answers,-2),1) Answer2,-1) Answer3
from questions q inner join (
  select q_id,group_concat(answer order by id) all_answers
  from answers 
  group by q_id
) a
on a.q_id = q.q_id

我使用','作为连接答案的分隔符。
请参见demo

如果答案中可能存在',',则可以通过在separator '@'中添加说group_concat()并使用'@'将其更改为任何其他字符在substring_index()中。
请参见demo

结果:

| q_id | question          | Answer1 | Answer2 | Answer3 |
| ---- | ----------------- | ------- | ------- | ------- |
| 1    | Colors in Rainbow | Violet  | Blue    | Yellow  |
| 2    | Colors in Tree    | Brown   | Orange  | Green   |