简体   繁体   English

查询此问题的最佳方法是什么?

[英]What is the best way to query this?

I have tables that look like this:我有看起来像这样的表:

questions:
id description
1   Q1
2   Q2

answers:
id question_id x y description
1     1        1 2   A1
2     1        3 4   A2
3     2        5 6   A3
4     2        7 8   A4

What I want to get is a query that can output this:我想得到的是一个可以 output 这个查询:

Q1 A1 1,2 A2 3,4
Q2 A3 5,6 A4 7,8

I've been pulling my hair for days now trying to figure this out.几天来我一直在拉头发,试图弄清楚这一点。 I'm doing this in PHP and MySQL so if anyone can shed some light out there, that'd be really great.我在 PHP 和 MySQL 中这样做,所以如果有人可以在那里阐明一些观点,那就太好了。

EDIT: I forgot to mention that I'm using CodeIgniter for this, too.编辑:我忘了提到我也在为此使用 CodeIgniter 。 So, that might help with the answers.所以,这可能有助于答案。

Considering that there might be a random number of answers per question, you cannot design a query that will return a fixed number of columns.考虑到每个问题可能有随机数量的答案,您无法设计一个返回固定数量列的查询。 You have to return a single result per question and then do a little bit of parsing in your code.您必须为每个问题返回一个结果,然后在代码中进行一些解析。

The GROUP_CONCAT function can be helpful for this kind of problem: GROUP_CONCAT function 可以帮助解决此类问题:

SELECT q.description, GROUP_CONCAT(
    CONCAT(a.description,' ',a.x,',',a.y) ORDER BY a.id
    SEPARATOR ' '
    ) AS answers
FROM questions q
  JOIN answers a ON a.question_id = q.id
GROUP BY q.description;

Will return将返回

+-------------+---------------+
| description | answers       |
+-------------+---------------+
| Q1          | A1 1,2 A2 3,4 |
| Q2          | A3 5,6 A4 7,8 |
+-------------+---------------+
2 rows in set (0.00 sec)

You can change the SEPARATOR value by whatever you want to parse the result in your code.您可以通过要在代码中解析结果的任何内容来更改SEPARATOR值。 You can use the ORDER BY clause of the GROUP_CONCAT function to order the answers in the returned result for each answer (here I ordered by answer id).您可以使用GROUP_CONCAT function 的ORDER BY子句对每个答案的返回结果中的答案进行排序(这里我按答案 id 排序)。

Edit : If you are sure that there will never be more than 4 answers per question, you can issue the following query to put each answer in its own column:编辑:如果您确定每个问题的答案永远不会超过 4 个,您可以发出以下查询以将每个答案放在自己的列中:

SELECT description,
  REPLACE(SUBSTRING(SUBSTRING_INDEX(answers, '$', 1), LENGTH(SUBSTRING_INDEX(answers, '$', 1 - 1)) + 1), '$', '') answer_1,
  REPLACE(SUBSTRING(SUBSTRING_INDEX(answers, '$', 2), LENGTH(SUBSTRING_INDEX(answers, '$', 2 - 1)) + 1), '$', '') answer_2,
  REPLACE(SUBSTRING(SUBSTRING_INDEX(answers, '$', 3), LENGTH(SUBSTRING_INDEX(answers, '$', 3 - 1)) + 1), '$', '') answer_3,
  REPLACE(SUBSTRING(SUBSTRING_INDEX(answers, '$', 4), LENGTH(SUBSTRING_INDEX(answers, '$', 4 - 1)) + 1), '$', '') answer_4
FROM (
    SELECT q.description, GROUP_CONCAT(
        CONCAT(a.description,' ',a.x,',',a.y) ORDER BY a.id
        SEPARATOR '$'
        ) AS answers
    FROM questions q
      JOIN answers a ON a.question_id = q.id
    GROUP BY q.description
  ) t;

Will return将返回

+-------------+----------+----------+----------+----------+
| description | answer_1 | answer_2 | answer_3 | answer_4 |
+-------------+----------+----------+----------+----------+
| Q1          | A1 1,2   | A2 3,4   |          |          |
| Q2          | A3 5,6   | A4 7,8   | A5 9,10  |          |
+-------------+----------+----------+----------+----------+
2 rows in set (0.00 sec)

I added an answer to the second question for the illustration.我为插图添加了第二个问题的答案。

select * from answers ORDER BY question_id

$question_id = 0;
$print_ln = null;
foreach ($result as $row) {
  if ($question_id != $row['question_id']) { 
     echo "<br>";
     $question_id = $row['question_id'];
     $print_ln = "Q" . $row['question_id'] . " " . $row['description'] . " " . $row['x'] . "," . $row['y'];
  } else { 
     $print_ln = $print_ln . " " . $row['description'] . " " . $row['x'] . "," . $row['y'];
  }
  echo $print_ln;
 }

Note, this code still needs a bit of work... its to give you an idea on how to do it.请注意,此代码仍需要一些工作......它可以让您了解如何执行此操作。

This query:这个查询:

SELECT 
      q.id
    , q.description
    , a.description
    , CONCAT(a.x, ',', a.y)
FROM questions AS q
    JOIN answers AS a
        ON a.question_id = q.id
ORDER BY q.id
       , a.id

will show:将会呈现:

| 1 | Q1 | A1 | 1,2 |
| 1 | Q1 | A2 | 3,4 |
| 2 | Q2 | A3 | 5,6 |
| 2 | Q2 | A4 | 7,8 |

What you describe as final result is called pivoting and it's not easy in MySQL and depends on the data you have.您所描述的最终结果称为旋转,在 MySQL 中并不容易,这取决于您拥有的数据。 For example, what should be shown if for a question, there are more than 2 answers?例如,如果一个问题的答案超过 2 个,应该显示什么?

And why will the result be this:为什么结果会是这样:

| Q1 | A1 | 1,2 | A2 | 3,4 | 
| Q2 | A3 | 5,6 | A4 | 7,8 |

and not like that?:不是那样的吗?:

| Q1 | A1 | 1,2 | A2 | 3,4 | 
| Q2 | A4 | 7,8 | A3 | 5,6 | 

Anyway, for maximum of 4 answers per questions and ordering per answers.id , this will work.无论如何,对于每个问题最多 4 个答案和每个answers.id排序,这将起作用。 It may be best though to use the previous query and do the pivoting in PHP, where you can handle variable number of columns without problem:最好使用前面的查询并在 PHP 中进行旋转,在这里您可以毫无问题地处理可变数量的列:

SELECT 
      q.id
    , q.description
    , ( SELECT a.description
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 0,1
      ) AS answer1
    , ( SELECT CONCAT(a.x, ',', a.y)
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 0,1
      ) AS xy1
    , ( SELECT a.description
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 1,1
      ) AS answer2
    , ( SELECT CONCAT(a.x, ',', a.y)
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 1,1
      ) AS xy2
    , ( SELECT a.description
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 2,1
      ) AS answer3
    , ( SELECT CONCAT(a.x, ',', a.y)
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 2,1
      ) AS xy3
    , ( SELECT a.description
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 3,1
      ) AS answer4
    , ( SELECT CONCAT(a.x, ',', a.y)
        FROM answers AS a
        WHERE a.question_id = q.id
        ORDER BY a.id  LIMIT 3,1
      ) AS xy4
FROM questions AS q
ORDER BY q.id  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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