1

我有 3 张桌子

  • questions (q_id, q_text)
  • answers (a_id, a_text, q_id)
  • correct_answers (q_id, a_id)

对于每个问题,答案表可以有最少 1 个和最多 4 个值

我需要一个纯 SQL 查询(连接或子查询)来获得下表作为结果

result (q_id, q_text, option1, option2, option3, option4, correct)

option1, option2, option3,option4都属于答案表并且可以是null,correct属于correct_answers

问题:

q_id  q_text
2     Capital of Pakistan is
3     Karachi is in africa
5     New dehli is _____ of india

答案:

a_id  a_text     q_id
1     Lahore     2
2     Islamabad  2
3     Karachi    2
4     Quetta     2
5     True       3
6     False      3
7     Capital    5

正确答案:

q_id  a_id
2     2
3     6
5     7

查询结果:

q_id  q_text                       option_1   option_2   option_3  option_4 correct
2     Capital of Pakistan is       Lahore     Islamabad  Karachi   Quetta   Islamabad
3     Karachi is in africa         True       False      null      null     False
5     New dehli is _____ of india  Capital    Null       Null      Null     Capital
4

3 回答 3

6

您没有指定什么 RDBMS,但既然您说 PL/SQL,我猜是 Oracle。

根据您的版本,您应该能够使用以下内容来对大多数数据库产品中的数据进行透视:

select q_id,
  q_text,
  max(case when rn = 1 then answer end) Option1,
  max(case when rn = 2 then answer end) Option2,
  max(case when rn = 3 then answer end) Option3,
  max(case when rn = 4 then answer end) Option4,
  CorrectAnswer
from
(
  select q.q_id,
    q.q_text,
    a1.a_text Answer,
    a2.a_text CorrectAnswer,
    row_number() over(partition by q.q_id order by a1.a_id) rn
  from questions q
  left join answers a1
    on q.q_id = a1.q_id
  left join Correct_answer ca
    on q.q_id = ca.q_id
  left join answers a2
    on ca.a_id = a2.a_id
)
group by q_id, q_text, CorrectAnswer
order by q_id

请参阅SQL Fiddle with Demo

如果您使用的是 Oracle 11g+,那么您可以使用以下PIVOT功能:

select q_id,
  q_text,
  Option1, Option2, Option3, Option4,
  CorrectAnswer
from
(
  select q.q_id,
    q.q_text,
    a1.a_text Answer,
    a2.a_text CorrectAnswer,
    row_number() over(partition by q.q_id order by a1.a_id) rn
  from questions q
  left join answers a1
    on q.q_id = a1.q_id
  left join Correct_answer ca
    on q.q_id = ca.q_id
  left join answers a2
    on ca.a_id = a2.a_id
)
pivot
(
  max(answer)
  for rn in ('1' as Option1, '2' as Option2, 
             '3' as Option3, '4' as Option4)
) piv
order by q_id

请参阅带有演示的 SQL Fiddle

于 2013-02-28T20:16:32.753 回答
2

这个适用于 ORACLE、MySQL、MS SQL Server 和 PostgreSQL

SELECT q_id, 
       q_text,
       (SELECT a_text
          FROM answers a1
         WHERE a1.q_id = q1.q_id
           AND (SELECT count(*) FROM answers a2 WHERE a1.q_id = a2.q_id AND a2.a_id < a1.a_id) = 0) as option1,
       (SELECT a_text
          FROM answers a1
         WHERE a1.q_id = q1.q_id
           AND (SELECT count(*) FROM answers a2 WHERE a1.q_id = a2.q_id AND a2.a_id < a1.a_id) = 1) as option2,
       (SELECT a_text
          FROM answers a1
         WHERE a1.q_id = q1.q_id
           AND (SELECT count(*) FROM answers a2 WHERE a1.q_id = a2.q_id AND a2.a_id < a1.a_id) = 2) as option3,
       (SELECT a_text 
          FROM answers a1
         WHERE a1.q_id = q1.q_id
           AND (SELECT count(*) FROM answers a2 WHERE a1.q_id = a2.q_id AND a2.a_id < a1.a_id) = 3) as option4,
       (SELECT a_text
          FROM answers a1
         WHERE a1.a_id = (select a_id from correct_answers c1 where c1.q_id = q1.q_id)) as correct
  FROM questions q1;

干杯!

于 2013-02-28T20:51:04.227 回答
-1

我将首先向表中添加一个PositionAnswers,其中包含一个唯一约束(q_id, Position)和一个域约束Position > 0 AND Position <= 4。无论如何,您可能想要一个Position专栏;通常最好在行具有自然顺序时对其进行显式排序,而不是尝试通过它们的代理键对它们进行排序或完全丢弃排序信息。

这使您可以更少地像这样查询数据库:

SELECT
        q.qid, q.q_text,
        a1.a_text AS option1, a2.a_text AS option2,
        a3.a_text AS option3, a4.a_text AS option4,
        ca.a_text AS correct
    FROM
        Questions q
        LEFT JOIN Answers a1 ON a1.q_id = q.q_id AND a1.Position = 1
        LEFT JOIN Answers a2 ON a2.q_id = q.q_id AND a2.Position = 2
        LEFT JOIN Answers a3 ON a3.q_id = q.q_id AND a3.Position = 3
        LEFT JOIN Answers a4 ON a4.q_id = q.q_id AND a4.Position = 4
        JOIN Correct_answer qca ON ca.q_id = q.q_id
        JOIN Anwsers ca ON ca.a_id = qca.a_id

你可以侥幸逃脱,因为你有固定数量的可能答案;更通用的解决方案可能需要动态 SQL 或应用层代码来透视结果集。

于 2013-02-28T20:18:05.390 回答