简体   繁体   中英

How to combine rows from two tables into a single table based on Foreign key, in MySQL.?

I have 2 tables in MySQL as shown below:

+------+-------+------------------+
| 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 is the field linking the two tables. Each Q_id has exactly 3 options as answers.

Now, I want to write a query in MySQL that gives the following table as output .

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

How do I do that.?

If they are all of the cases then you can use simple CASE WHEN and MAX combination here.

Working Solution

SELECT Q_ID ,QUESTION,
MAX(CASE WHEN MOD(ID,3)=1 THEN ANSWER END) AS ANS1,
MAX(CASE WHEN MOD(ID,3)=2 THEN ANSWER END) AS ANS2,
MAX(CASE WHEN MOD(ID,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 ,     1 AS Q_ID, 'Violet' AS ANSWER UNION ALL
SELECT 2 AS ID ,     1 AS Q_ID, 'Blue  ' AS ANSWER UNION ALL
SELECT 3 AS ID ,     1 AS Q_ID, 'Yellow' AS ANSWER UNION ALL
SELECT 4 AS ID ,     2 AS Q_ID, 'Brown ' AS ANSWER UNION ALL
SELECT 5 AS ID ,     2 AS Q_ID, 'Orange' AS ANSWER UNION ALL
SELECT 6 AS ID ,     2 AS Q_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

Edit:

As stickybit said there is a flaw in my first answer. For getting rid of this flaw i used ROW_NUMBER . This edit made by guidance that come from stickybit. Thank you for your advice. (Window functions are work only mysql version 8.0 or above.)

Source

SELECT Q_ID ,QUESTION,
MAX(CASE WHEN MOD(RN,3)=1 THEN ANSWER END) AS ANS1,
MAX(CASE WHEN MOD(RN,3)=2 THEN ANSWER END) AS ANS2,
MAX(CASE WHEN MOD(RN,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 ,     1 AS Q_ID, 'Violet' AS ANSWER UNION ALL
SELECT 4 AS ID ,     1 AS Q_ID, 'Blue' AS ANSWER UNION ALL
SELECT 7 AS ID ,     1 AS Q_ID, 'Yellow' AS ANSWER UNION ALL
SELECT 10 AS ID ,     2 AS Q_ID, 'Brown' AS ANSWER UNION ALL
SELECT 13 AS ID ,     2 AS Q_ID, 'Orange' AS ANSWER UNION ALL
SELECT 16 AS ID ,     2 AS Q_ID, 'Green' AS ANSWER 
)
SELECT row_number() OVER (PARTITION BY TAB1.Q_ID ORDER BY TAB2.ID) as rn, 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

在此处输入图像描述

One way is to use subqueries with LIMIT and OFFSET .

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
Note that you need some column(s) to ORDER BY here as otherwise there is no guaranteed order which could lead to some answer show up more than once or not at all.

Use group_concat() in the table answers to concat the answers in the correct order and then join to questions where you use substring_index() to split:

select q.q_id, q.question,
       substring_index(all_answers, ',', 1) Answer1,
       substring_index(substring_index(all_answers, ',', -2), ',', 1) Answer2,
       substring_index(all_answers, ',', -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

I use ',' as the separator for the concatenated answers.
See the demo .

If there is a case that ',' could exist inside an answer then you can change it to any other character, by adding say separator '@' in group_concat() and using '@' in substring_index() .
See the demo .

Results:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM