2009-07-27 6 views
0

Я уверен, что это общий запрос, но я не уверен, как его лучше всего сформулировать.SQL: выбор родителей и их детей

У меня есть две таблицы:

Questions { Id, Text... } 
Answers { Id, QuestionId, Text...} 

Я хотел бы получить список Вопросы и их Ответы, так что результаты могут быть представлены следующим образом:

  • Вопрос A
    • 1-й ответ на вопрос A
    • второй ответ на вопрос
    • 3-го ответа на вопрос
  • вопрос В
    • 1-ый ответ на вопрос B ... и т.д.

Предположим, что это некоторые критерии выбора в таблице вопросов.

Очень неэффективный метод заключается в выборе всех соответствующих вопросов, а затем для каждого выбора всех ответов. Другим неэффективным методом будет использование LEFT OUTER JOIN.

Какой самый эффективный и простой способ получить ответы на вопросы и ответы? Можно ли это сделать в одном запросе?

+2

левое внешнее соединение не будет вообще неэффективным. im не уверен, почему вы думаете, что – Shawn

+0

Согласен - см. мой ответ ниже. JOIN - для этой цели. – Christian

ответ

2

Для MySQL (не MSSQL) Что-то вроде этого будет работать;

SELECT q.text, a.text 
FROM questions q 
LEFT JOIN answers a ON 
    q.quiestionid = q.id 
GROUP BY q.id, a.id 
ORDER BY q.id 

Сообщите мне, если у вас есть q.

+0

Почему вы не думаете, что работали бы на MSSQL? Вы только что написали ANSI SQL. Синтаксис будет отлично работать в SQL Server. – Eric

+1

afaik, ANSI-совместимый rdbms требует, чтобы столбцы в предложении SELECT также отображались в предложении GROUP BY. поэтому q.text и a.text должны быть включены в предложение GROUP BY. Пример christian не будет работать на PostgreSQL и MSSQL. выше будет работать только на pg и mssql, используя это: GROUP BY q.id, a.id, q.text, a.text –

+1

, но поскольку .id-поля являются первичными ключами и не повторятся, почему бы не просто сбросить бесполезную группу ?! –

1

Почему вы думаете, что левое соединение было бы неэффективным? Вы получите несколько повторяющихся данных по вопросам, на которые ответили много раз, но это всего лишь несколько лишних байтов над проводом, о чем не о чем беспокоиться.

Один ответ, который был дан, отлично работает (в любом реальном движке sql, включая mssql, sqlite и т. Д., А также mysql, как было предложено), но является избыточным (у него есть групповой доступ к первичным ключам, t получить дублирование в любом случае). Таким образом, следующий простой и опечатка фиксированной версии хорошо и быстро:

SELECT q.id, q.text, a.id, a.text 
    FROM questions q 
    LEFT JOIN answers a ON a.questionid = q.id 
ORDER BY q.id 

Ваш клиентский код должен просто заметить, когда q.id изменения для того, чтобы группы и отображения вещей «иерархически», как вы хотите - как это сделать это зависит от используемого вами языка на стороне клиента, например, в Python вы бы использовали itertools.groupby, чтобы сделать это очень просто (вам не нужна группа на стороне SQL-сервера, но вам она нужна на стороне клиента, независимо от того, с предоставленным языком средством, как на Python, или путем его реализации самостоятельно, чтобы отобразить иерархию по вашему желанию).

+0

Да, я думал, что неэффективность будет в дублированных данных - если в худшем случае может быть от 20 до 100 ответов. Учитывая простоту, я все равно попробую и отложите дальнейшую оптимизацию после проверки производительности. – cbp

Смежные вопросы