【问题标题】:Sorting rows before joining one table to multiple tables?在将一个表连接到多个表之前对行进行排序?
【发布时间】:2015-06-07 14:39:21
【问题描述】:

我有两张表:问题和答案。

这是 question 表架构的简化版本:

question_id      integer PRIMARY KEY
question_title   varchar(250)
answers_id       SERIAL UNIQUE

这是 answer 表架构的简化版本:

answer_id        integer REFERENCES question (answers_id)
answer_text      varchar(500)
is_top_answer    boolean

我想在一个查询中完成三个任务:

  1. 根据包含 question_id 的参数从问题表中选择一行。
  2. 将答案表中的恰好一个行与查询的第 1 步中从问题表中检索到的行相结合,其中答案表中的一行满足以下两个条件:1. is_top_answer 为真,并且 2. answer_id 等于在查询的第 1 步中从问题表中检索到的行的 answers_id。
  3. 将答案表中的可变数量行与查询步骤 1 中从问题表中检索到的行相结合,其中答案表的 answer_id 与从问题表中检索到的行的 answers_id 匹配在查询的第 1 步中。

我已使用以下 SQL 语句填充问题和答案表:

insert into question values (1, 'Where is the best sushi restaurant?', 10);
insert into answer values (10, 'In California', 'false');
insert into answer values (10, 'In Seattle', 'true');
insert into answer values (10, 'In New York', 'false');

如果我要使用代表问题表中保存的 question_id 的参数查询问题表,我希望得到以下行:

 question_id |           question_title            | answers_id |   answer_text | is_top_answer  |   answer_text | is_top_answer  |   answer_text | is_top_answer  |
-------------+-------------------------------------+------------+---------------+----------------+---------------+----------------+---------------+----------------+
           1 | Where is the best sushi restaurant? |         10 | In Seattle    | f              | In California | f              | In New York   | f              |

我尝试使用子查询 SELECT 语句,该语句尝试通过返回答案表中的所有行来满足查询的任务 2 和 3,其中 answer_id 与问题表行的 answers_id 匹配,按 is_top_answer 的升序值排序,在 LEFT JOIN 语句中,但我没有成功,因为 postgres 抱怨“子查询必须只返回一列”错误。这是查询:

    SELECT (q.question_id, q.question_title), 
        (SELECT answer_id, answer_text FROM answer 
            WHERE answer_id = q.answers_id 
            ORDER BY is_top_answer ASC) 
    FROM question q 
    RIGHT JOIN answer a ON a.answer_id = q.answers_id 
    WHERE q.question_id = $1

我也试过这个查询:

    select * from question inner join answer on question.answers_id = answer.answer_id 
    where question.question_id = 1 
    order by answer.is_top_answer;

这个查询的结果是三行:

 question_id |           question_title            | answers_id | answer_id |  answer_text  | is_top_answer 
-------------+-------------------------------------+------------+-----------+---------------+---------------
           1 | Where is the best sushi restaurant? |         10 |        10 | In California | f
           1 | Where is the best sushi restaurant? |         10 |        10 | In New York   | f
           1 | Where is the best sushi restaurant? |         10 |        10 | In Seattle    | t

每一行都有问答表中一行的副本。我不是在寻找三行,而是在尝试创建一个查询,该查询返回一行,该行是问题表中的一行和答案表中的多行的组合。

任何关于在单个查询中完成这三个任务的建议将不胜感激。谢谢

【问题讨论】:

  • 请编辑您的问题并提供示例数据和所需结果。我(一方面)发现很难遵守你的规则。另外,确定您使用的是 MySQL 还是 Postgres,并适当地标记问题。
  • 在第 3 步中,您想获得问题的所有答案(顶部和不是),而在第 2 步中,您只希望得到最佳答案?这就是我的理解
  • @Skaros Ilias 是的,完全正确。
  • 所以,您需要所有答案和最佳答案
  • 是的,按照特定的顺序。我想先加入最佳答案,然后我想加入与从问题表中查询的行的 answers_id 具有相同 answer_id 的所有其他答案。

标签: sql postgresql


【解决方案1】:

这行得通吗? (没有测试过)

select * from question inner join answer on 
    questions.answers_id=answer.answer_id where question.question_id = $1

这将带来所有答案。您无法同时获得所有答案和最佳答案。它没有任何意义。如果你得到所有这些,你也会得到最好的答案。也许你可以做

select * from question inner join answer on 
    questions.answers_id=answer.answer_id where question.question_id = $1
    order by asnwer.is_top_answer

为了在列表中获得第一名

【讨论】:

  • 感谢您的帮助。查询确实运行没有错误,但它没有返回正确的结果。查询返回问题的副本,其中包含具有匹配 answers_id 的每个答案。我正在尝试创建一个查询,该查询返回由问题表中的一行和答案表中的几行组成的行。
  • 用一个你想得到什么的例子来编辑你的问题,也许这段代码给了你什么
  • llias,很抱歉造成混乱。我已经进行了请求的编辑。
【解决方案2】:

如果你想要一行,那么使用聚合:

select q.*,
       string_agg(answer_text, '|' order by is_top_answer desc) as answers
from question q inner join
     answer a 
     on q.answers_id = a.answer_id
where q.question_id = $1;

您问题中的数据结构似乎搞砸了。通常,每个问题都有一个唯一的自动递增主键,称为question_id。每个答案都有一个唯一的自动递增主键,称为answer_id。每个答案还将通过名为question_id 的字段链接回该问题。但是,此答案遵循问题中的命名约定。

【讨论】:

  • 你说得对,问题表中的 answers_id 是完全没有必要的。我会去掉 questions 表中的 answers_id,我会在 answer 表的 answer_id 中定义对 question_id 的引用。
猜你喜欢
  • 2015-07-29
  • 1970-01-01
  • 2021-02-11
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
  • 1970-01-01
  • 2012-11-27
  • 1970-01-01
相关资源
最近更新 更多