简体   繁体   中英

Sorting rows before joining one table to multiple tables?

I have two tables: question and answer.

Here is a simplified version of the question table's schema:

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

Here is a simplified version of the answer table's schema:

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

I would like to accomplish three tasks in a single query:

  1. Select a row from the question table based off of a parameter that contains a question_id.
  2. Join exactly one row from the answer table with the row retrieved from the question's table in step 1 of the query where the two following conditions are satisfied by a row in the answer table: 1. the is_top_answer is true and 2. the answer_id equals the answers_id of the row retrieved from the question table in step 1 of the query.
  3. Join a variable amount of rows from the answer table with the row retrieved from the question's table in step 1 of the query where the answer table's answer_id matches the answers_id of the row retrieved from the question table in step 1 of the query.

I have populated the question and answer tables with the following SQL statements:

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');

If I were to query the question table with a parameter that represents a question_id held in the question table, I would expect the following row as a result:

 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              |

I have tried to use a subquery SELECT statement, which attempts to satisfy tasks 2 and 3 of the query by returning all the row from the answer table where answer_id matches the answers_id of the question table's row ordered by ascending values of the is_top_answer, within a LEFT JOIN statement, but I have not had success because the postgres complains with a "subquery must return only one column" error. Here is the query:

    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

I have also tried this query:

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

The result of this query is three rows:

 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

Each row has a copy of a row from the question and answer tables. I am not looking for three rows, I am trying to create a query that returns one row that is a combination of one row from the question table and multiple rows from the answer table.

Any advice about accomplishing the three tasks in a single query would be greatly appreciated. Thanks

does this work? (havent tested it)

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

this will bring all of the answers. you can not get both all the ansers and the best answers. it makes no sence. if you get all of them you will get the best answer as well. maybe you can do

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

in order to get the top answer first on the list

If you want one row, then use aggregation:

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;

The data structure in your question seems messed up. Normally, each question would have a unique auto-incremented primary key called question_id . Each answer would have a unique auto-incremented primary key called answer_id . Each answer would also have a link back to the question via a field called question_id . However, this answer follows the naming conventions in the question.

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