MySQL считает всех детей независимо от того, сколько их - PullRequest
1 голос
/ 07 октября 2011

Я разрабатываю простую систему, в которой есть неограниченное количество категорий и предметов в каждой категории. Например, могут быть категории внутри категорий и т. Д. (Категория 1 -> Категория 2 -> Категория 3), содержащие все элементы. Я хочу отобразить общее количество элементов для каждой категории и ВСЕХ их подкатегорий. Я пытаюсь выяснить цикл, чтобы сделать это, но в основном я терплю неудачу. Я строю в PHP / MySQL. Моя схема таблицы категорий - это категория (id, id_parent), где id - автоинкремент, а id_parent - то, находится ли она в другой категории (по умолчанию 0). Моя схема элементов это элементы (id, id_category). Очевидно, есть и другие столбцы, но это единственные, которые имеют значение, я верю. Может кто-нибудь, пожалуйста, помогите мне разработать структуру цикла, чтобы придумать общее количество элементов для категории, в которой они находятся (включая все элементы подкатегорий). Вот что я начал, хотя чувствую, что это очень, очень неправильно.

function CountChildDownloads($id_category)
{
global $smcFunc;
$x = array();
$total = 0;

$request = $smcFunc['db_query']('', '
    SELECT COUNT(*) AS items FROM {db_prefix}xld_downloads
    WHERE id_category = '.$id_category.''
);

$total += $request['items'];

$request = $smcFunc['db_query']('', '
    SELECT id FROM {db_prefix}xld_categories
    WHERE id_parent = '.$id_category.''
);

if($smcFunc['db_num_rows']($request) > 0)  {
    while($row = $smcFunc['db_fetch_assoc']($request)) {
        $x[] = $row['id'];
    }
}

foreach ($x as $id)
{
    $y = array();
    $z = 0;

    $request = $smcFunc['db_query']('', '
        SELECT COUNT(*) AS items FROM {db_prefix}xld_downloads
        WHERE id_category = '.$id.''
    );

    $z += $request['items'];

    $request = $smcFunc['db_query']('', '
        SELECT id FROM {db_prefix}xld_categories
        WHERE id_parent = '.$id.''
    );

    if($smcFunc['db_num_rows']($request) > 0)  {
        while($row = $smcFunc['db_fetch_assoc']($request)) {
            $y[] = $row['id'];
        }
    }

    while (count($y) > 0)
    {
        $id_y = $y[0];

        $request = $smcFunc['db_query']('', '
            SELECT id FROM {db_prefix}xld_categories
            WHERE id_parent = '.$id_y.''
        );

        if($smcFunc['db_num_rows']($request) > 0)  {
            while($row = $smcFunc['db_fetch_assoc']($request)) {
                $y[] = $row['id'];
            }
        }

        $request = $smcFunc['db_query']('', '
            SELECT COUNT(*) AS items FROM {db_prefix}xld_downloads
            WHERE id_category = '.$id_y.''
        );

        $z += $request['items'];

        unset($y[0]);
        array_values($y);
    }

    $total += $z;
}

return $total;
}

$ smcFunc - это просто системный способ выполнения запросов. Это серверная часть MySQL.

Рабочая функция (потребуется обновить до стандартных вызовов MySQL, если не используется SMF). Спасибо, Лукас.

function CountChildDownloads($id_category)
{
global $smcFunc;
$x = array();
$total = array();
$total['downloads'] = 0;
$total['views'] = 0;

$request = $smcFunc['db_query']('', '
    SELECT views FROM {db_prefix}xld_downloads
    WHERE id_category = '.$id_category.''
);

if($smcFunc['db_num_rows']($request) > 0)  {
    while($row = $smcFunc['db_fetch_assoc']($request)) {
        $total['downloads']++;
        $total['views'] += $row['views'];
    }
}

$request = $smcFunc['db_query']('', '
    SELECT id FROM {db_prefix}xld_categories
    WHERE id_parent = '.$id_category.''
);

if($smcFunc['db_num_rows']($request) > 0)  {
    while($row = $smcFunc['db_fetch_assoc']($request)) {
        $x[] = $row['id'];
    }
}

foreach ($x as $id)
{
    $y = array();
    $z = 0;
    $w = 0;

    $request = $smcFunc['db_query']('', '
        SELECT views FROM {db_prefix}xld_downloads
        WHERE id_category = '.$id.''
    );

    if($smcFunc['db_num_rows']($request) > 0)  {
        while($row = $smcFunc['db_fetch_assoc']($request)) {
            $z++;
            $w += $row['views'];
        }
    }

    $request = $smcFunc['db_query']('', '
        SELECT id FROM {db_prefix}xld_categories
        WHERE id_parent = '.$id.''
    );

    if($smcFunc['db_num_rows']($request) > 0)  {
        while($row = $smcFunc['db_fetch_assoc']($request)) {
            $y[] = $row['id'];
        }
    }

    while (count($y) > 0)
    {
        $id_y = $y[0];

        if (!empty($id_y))
        {
            $request = $smcFunc['db_query']('', '
                SELECT id FROM {db_prefix}xld_categories
                WHERE id_parent = {int:id_parent}',
                array(
                    'id_parent' => $id_y,
                )
            );

            if($smcFunc['db_num_rows']($request) > 0)  {
                while($row = $smcFunc['db_fetch_assoc']($request)) {
                    $y[] = $row['id'];
                }
            }

            $request = $smcFunc['db_query']('', '
                SELECT views FROM {db_prefix}xld_downloads
                WHERE id_category = {int:id_category}',
                array(
                    'id_category' => $id_y,
                )
            );

            if($smcFunc['db_num_rows']($request) > 0)  {
                while($row = $smcFunc['db_fetch_assoc']($request)) {
                    $z++;
                    $w += $row['views'];
                }
            }
        }

        unset($y[0]);
        $y = array_values($y);

    }

    $total['downloads'] += $z;
    $total['views'] += $w;
}

return $total;
}

1 Ответ

1 голос
/ 07 октября 2011

(Существует множество подходов к вложенным циклам / запросам. Идея изменения структуры состоит в том, чтобы иметь отдельную таблицу, в которой перечислены все дочерние элементы каждой категории ... и убедиться, что у нее есть не только непосредственные дочерние элементы, но иимеет дочерних и вспомогательных дочерних элементов ... как 1 имеет дочернего элемента 2, 2 имеет дочернего элемента 3, 1 имеет дочернего элемента 3, 3 имеет дочернего элемента 5, 1 имеет дочернего элемента 5 .. и т. д.) НО, для текущегоситуация ..

Одна структура цикла может быть:

Начать набор результатов.||Запрос для всех идентификаторов категории, где parent = 0. ||Добавьте каждый в массив (X).||Закрыть набор результатов.

Для каждого идентификатора в массиве (X):

  • Установить новую переменную подсчета (z).
  • Установить новый дочерний идентификатормассив (Y).

  • Начать набор результатов.||Количество запросов * для всех элементов с категорией = текущий идентификатор x ||Добавить к счетной переменной (z) ||Закрыть набор результатов.

  • Запустить набор результатов.||Запрос для всех идентификаторов категории, где parent = текущий идентификатор x ||Добавьте все в дочерний массив идентификаторов (Y).||Закрыть набор результатов.

  • при длине дочернего массива (Y)> 0

    • идентификатор категории y = первый элемент массива (Y)

    • Запустить набор результатов.||Запрос для всех идентификаторов категории, где parent = текущий идентификатор y.||Добавьте все в дочерний массив идентификаторов (Y).||Закрыть набор результатов.

    • Запустить набор результатов.||Количество запросов * для всех элементов с категорией = текущий идентификатор y ||Добавить к счетной переменной (z) ||Закрыть набор результатов.

    • удалить первый элемент из массива (Y)

  • продолжить, пока цикл

  • На данный момент у вас есть окончательное количество элементов (z) для идентификатора категории x ... сделайте что-нибудь с этим, затем продолжите цикл for

Конец дляпетля

...