[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Выборка из двух разных таблиц
Dimaz
Всем привет. Подскажите, пожалуйста, как правильно сделать выборку из двух таблиц. В первой таблице хранятся вопросы, а во второй, соответствующие им варианты ответов. Я делаю так:
SELECT tests.questions, otvety.answers 
FROM tests, otvety
WHERE tests.id = otvety.test_id

tests.id это уникальный идентификатор с автоинкрементом в таблице tests.
id | questions
1 | первый вопрос
2 | второй вопрос
otvety.test_id содержит идентификаторы вопросов, к которым относятся ответы.
test_id | answers
__1__ | вариант ответа 1
__1__ | вариант ответа 2
__1__ | вариант ответа 3
Здесь все варианты относятся к первому вопросу, т.е. к вопросу с id = 1.
В результате данного запроса, получаю следующую результирующую таблицу.
questions | answers
вопрос 1 | ответ 1
вопрос 1 | ответ 2
вопрос 1 | ответ 3
Полученные результаты нужно записать в ассоциативный массив, а затем передать клиенту в формате JSON. Функция json_encode.
Вопрос в том, как это сделать, чтобы не записывать вопрос несколько раз, так как они повторяются в таблице, напротив каждого ответа, соответствующего ему.
Вообще я представляю, полученный JSON таким:
{"question": "вопрос 1", "answers": [{"answer": "ответ 1"}, {"answer": "ответ 2"}, {"answer": "ответ 3"}]}
Dimaz
Неужели никто не знает? Случай не такой уж и редкий я думаю на практике. У меня есть предположение, что нужно добавить в результирующую таблицу колонку test_id.
questions | answers | test_id
вопрос 1 | ответ 1 | __1__
вопрос 1 | ответ 2 | __1__
вопрос 1 | ответ 3 | __1__
вопрос 2 | ответ 1 | __2__
вопрос 2 | ответ 2 | __2__
вопрос 2 | ответ 3 | __2__
Т.е. добавить вопрос в ассоциативный массив только один раз, затем добавлять варианты ответов, до тех пор пока test_id не будет равно 2, что означает, что дальше идет уже другой вопрос. Это всего лишь мое предположение. Как это делается по стандарту я понятия не имею. unsure.gif
Valick
__1__ - это прямо так и лежит в базе?

_____________
Стимулятор ~yoomoney - 41001303250491
Dimaz
Цитата (Valick @ 29.01.2013 - 18:19)
__1__ - это прямо так и лежит в базе?

Это я специально так сделал. Просто на некоторых форумах стоит автоматическое удаление лишних пробелов.
Valick
Цитата
Это я специально так сделал.

вообще-то это был намек на то чего не должно быть
у вас с организацией БД проблема, до массивов далеко еще

_____________
Стимулятор ~yoomoney - 41001303250491
Dimaz
Цитата (Valick @ 29.01.2013 - 18:51)
Цитата
Это я специально так сделал.

вообще-то это был намек на то чего не должно быть
у вас с организацией БД проблема, до массивов далеко еще

В чем именно проблема? Уж если начали, то поясните, пожалуйста.
Valick
таблица tests, тут все нормально
значимые поля
id(int auto_increment) | questions(varchar)
сюда же можно добавить время добавления вопроса (тип поля timestamp или datetime) в БД и например автора (тип поля int так как скорее всего это будет идентификатор юзера)
сюда же для расширения функционала можно добавить количество правильных ответов, при ситуации когда их может быть больше одного (тип поля int)
таблица otvety
значимые поля
id(int auto_increment) | test_id(int) | answers(varchar) | right(int или set или enum)

выбора вопросов - ответов
SELECT o.id, t.id, t.questions, o.answers
FROM otvety o
LEFT JOIN tests t ON o.test_id=t.id

можно сделать немного хитрее и сгруппировать по полю t.id используя GROUP_CONCAT для o.answers, через опеределенный разделитель, тогда запихать выборку в массив необходимого формата по средствам explode, как два пальца об асфальт

_____________
Стимулятор ~yoomoney - 41001303250491
Zzepish

SELECT *
FROM tests
LEFT JOIN
otvety
ON
tests.id = otvety.test_id
FROUP BY `tests.id`
Valick
<?php
include('connect.php');
$query="SELECT o.id oid, t.id tid, t.questions, GROUP_CONCAT(o.answers) answers
FROM otvety o
LEFT JOIN tests t
ON o.test_id=t.id
GROUP BY t.id"
;
$res=mysql_query($query);
if($res){
while($m=mysql_fetch_assoc($res)) $q[$m[questions]]=explode(",",$m[answers]);
}
echo "<PRE>";
print_r($q);
echo "</PRE>";
?>


_____________
Стимулятор ~yoomoney - 41001303250491
Dimaz
Цитата
можно сделать немного хитрее и сгруппировать по полю t.id используя GROUP_CONCAT для o.answers, через опеределенный разделитель, тогда запихать выборку в массив необходимого формата по средствам explode, как два пальца об асфальт

Раньше как раз таки я так и делал. Только разделял не на сервере, а на клиенте, методом JS split(','). Но на одном форуме мне сказали, что так делать нельзя, нужно две таблицы создавать. А была у меня только одна таблица, в которой хранились как вопросы так и ответы, перечисленный через запятую. Ну раз так неправильно, я решил сделать две таблицы, одна с вопросами, а другая с ответами. Все пришло к тому, что я вернулся к тому от чего пытался уйти, по многочисленным "просьбам". Вы мне предлагаете объединить все ответы в одну строку и потом разделять функцией explode. По сути если я так сделаю, то ничего принципиально нового у меня не получится. Может тогда есть смысл оставить все как есть?
И еще, я так и не понял, что у меня было не правильно в таблице. Все что вы сделали, так это дописали мою таблицу, добавили в нее новые поля, в которых у меня нет необходимости. Никаких id-ов юзеров у меня не будет. Правильных ответов тоже. Это же тесты, какие там могут быть правильные ответы. Будут балы, напротив каждого ответа.
Valick
Цитата
перечисленный через запятую

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

нет это не так, хранение и сборка при выборке - это разные вещи.
Цитата
И еще, я так и не понял, что у меня было не правильно в таблице

в таблице №2 у вас не было указано id строки и test_id имело какое-то странное содержание.
Цитата
Правильных ответов тоже. Это же тесты, какие там могут быть правильные ответы. Будут балы, напротив каждого ответа.

я думал у вас нормальные тесты, а это лохотесты аля желтая пресса sad.gif

_____________
Стимулятор ~yoomoney - 41001303250491
Guest
Цитата
в таблице №2 у вас не было указано id строки и test_id имело какое-то странное содержание.

Что странного? test_id это внешний ключ, ссылающийся на первичный ключ поля id таблицы tests. Все ответы с test_id = 1, относятся к вопросу с id =1. Так и не понял, что тут не правильно. А как иначе то можно? И нужно ли?
Цитата
я думал у вас нормальные тесты, а это лохотесты аля желтая пресса

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

А разве получить данные из одной таблице не быстрее, чем получать из двух, а потом еще и объединять записи. Сколько действий. Не думаю, что это будет работать быстрее.
Что-то мне подсказывает, что вряд ли для этих целей используют GROUP_CONCAT. Читал в интернете, многие программисты даже вообще не знают об этой функции.
Valick
Цитата
Что странного?

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

Именно поэтому достоверность такого теста - фуфло
но о том что это психические тесты надо было указать в самом первом посте и мы бы с вами на эту тему не разговаривали.
Цитата
А разве получить данные из одной таблице не быстрее, чем получать из двух, а потом еще и объединять записи.

Быстрее, но еще раз повторю, только в том случае если кроме выборки вы с этими данными ничего делать не собираетесь. И еще раз повторю (надеюсь последний) в таком случае это лучше хранить в файле, это будет еще быстрее. А вот если вам нужно хотя бы отсортировать вопросы в каком либо порядке при помощи БД, то сразу поймете почему не надо хранить данные в поле через запятую. Существуют правила нормализации которые следует учитывать при организации структуры БД.
Цитата
Что-то мне подсказывает, что вряд ли для этих целей используют GROUP_CONCAT.

Это уже ваши проблемы
Цитата
Читал в интернете, многие программисты даже вообще не знают об этой функции.

Это уже их проблемы

_____________
Стимулятор ~yoomoney - 41001303250491
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.