PHP / mySQL - как извлечь вложенные строки в многомерный массив

Исходя из другого моего вопроса, где я научился никогда не использовать db-запросы внутри циклов, я, следовательно, должен научиться извлекать все данные удобным способом, прежде чем проходить через него.

Допустим, у меня есть две таблицы «весы» и «предметы». Каждый элемент в элементах принадлежит одной шкале в масштабах и связан с внешним ключом (scaleID). Я хочу извлечь все эти данные в структуру массива в одном запросе, так что первое измерение - это все шкалы со всеми столбцами и вложенные во все элементы одной шкалы всех столбцов.

Результат будет примерно таким:

scale 1, scaleParam1, scaleParam2, ...
....item1, itemParam1, itemParam2, ...
....item2, itemParam1, itemParam2, ...
scale 2, scaleParam2, scaleParam2, ...
....item1, itemParam1, itemParam2, ...
....item2, itemParam1, itemParam2, ...

До сих пор я делал в основном левые соединения для личных отношений. Это один ко многим, и я просто не могу обдумать это.

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

позже я хотел бы перебрать его с помощью вложенных циклов foreach.

Может быть, просто у меня болит голова ...

10.12.2008 18:49:27
2 ОТВЕТА
РЕШЕНИЕ

Запрос должен выглядеть примерно так:

SELECT * FROM scales
INNER JOIN items ON scales.id = items.scale_id

Если вы хотите выполнить итерацию с помощью вложенных циклов, вам нужно будет вытащить эти данные в массив - надеюсь, вы не будете тянуть их назад так сильно, что они будут поглощать слишком много памяти.

$scales = array();

while ($row = mysql_fetch_assoc($data))
{
    if (!isset($scales[$row['scale_id']]))
    {
        $row['items'] = array();
        $scales[$row['scale_id']] = $row;
    }

    $scales[$row['scale_id']]['items'][] = $row;
}

Затем вы можете просмотреть:

foreach ($scales as $scale)
{
    foreach ($scale['items'] as $item)
        ; //... do stuff
}

Примечание: это несколько наивно в том, что $ scale и $ item будут содержать поля из ОБА таблиц ... если это проблема, вам нужно изменить назначения в цикле выше, чтобы вытащить только те поля, которые вы хотите.

6
21.01.2009 15:46:33
вау, у вас есть масса принятых ответов, удивительно. спасибо за это, также может оказаться на вершине.
markus 10.12.2008 19:31:25
Что касается вопроса, который породил этот вопрос, и вашего комментария о потреблении слишком большого количества памяти, я бы предпочел иметь большой массив, скажем, 1 МБ ОЗУ, чем выполнять много (десятки?) Запросов.
TravisO 10.12.2008 20:29:19
Кроме того, хорошая работа по использованию mysql_fetch_assoc, многие люди делают mysql_fetch_array, что неэффективно.
TravisO 10.12.2008 20:30:54
Тем временем я попробовал его, и ваше решение не совсем корректно, по крайней мере, в моем сценарии, часть if (! Isset ($ scale [$ row ['scale_id']]])) ошибочно генерирует правильный массив - структура ... Смотрите мое решение в моем собственном ответе.
markus 11.12.2008 02:32:31
Упс, исправлено отсутствие ['items']
Greg 21.01.2009 15:46:53

Может быть проще сначала получить все весы, а затем все предметы.

//first get scales
while ($row = fetchrowfunctionhere()) {
    $scale = $scales->createFromArray($row);
}

//then get items
$lastId = null;
while ($row = fetchrowfunctionhere()) {
    $scaleId = $row['scaleID'];
    if ($lastId != $scaleId) {
        $scale = $scales->getByScaleId($scaleId);
    }
    $item = $items->createFromArray($row);
    $scale->addItem($item);
    $lastId = $scaleId;
}

или все в одном sql

$lastId = null;
while ($row = fetchrowfunctionhere()) {
    $scaleData = array_slice($row, 0, 5, true);
    $itemData = array_slice($row, 5, 5, true);
    $scaleId = $scaleData['scaleID'];
    if ($lastId != $scaleId) {
        $scale = $scales->createFromArray($scaleData);
    }
    $item = $items->createFromArray($itemData);
    $scale->addItem($item);
    $lastId = $scaleId;
}

все как одно счастливое множество

while ($row = fetchrowfunctionhere()) {
    $scaleData = array_slice($row, 0, 5, true);
    $itemData = array_slice($row, 5, 5, true);
    $scaleId = $scaleData['scaleID'];
    if (!isset($scales[$scaleId])) {
        $scales[$scaleId] = $scaleData;
    }
    $itemId = $itemData['itemID'];
    $scales[$scaleId]['items'][$itemId] = $itemData;
}
1
10.12.2008 19:19:45
Я должен признать, что мне придется изучить ваши решения, так как я не совсем понимаю, что они делают.
markus 10.12.2008 19:38:23
Первые 2 являются объектами, что облегчает задачу. 3-й с массивами. Вы не указали mysql в своем тексте (но теперь я вижу тег mysql), поэтому я написал обобщенное имя функции вместо mysql_fetch_assoc.
OIS 10.12.2008 21:10:36