1. C# / Говнокод #2131

    +101.2

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    var r = from t in ds.ProductTags
    		where t.ProductTagID == tag
    			|| t.Parent.ProductTagID == tag
    			|| t.Parent.Parent.ProductTagID == tag
    			|| t.Parent.Parent.Parent.ProductTagID == tag
    			|| t.Parent.Parent.Parent.Parent.ProductTagID == tag
    			|| t.Parent.Parent.Parent.Parent.Parent.ProductTagID == tag
    			|| t.Parent.Parent.Parent.Parent.Parent.Parent.ProductTagID == tag
    			|| t.Parent.Parent.Parent.Parent.Parent.Parent.Parent.ProductTagID == tag
    			|| t.Parent.Parent.Parent.Parent.Parent.Parent.Parent.Parent.Parent.ProductTagID == tag
    		select t;

    Это мой код. Надоело писать рекурсивные СTE чтобы выбрать всех детишек. Спросил у кастомера можно ли ограничить вложенность. Он согласился ;).. На свою голову ;).

    Запостил: Mike Chaliy, 11 Ноября 2009

    Комментарии (14) RSS

    • а SQL как?
      Ответить
      • База данных, видимо, по-умному организована, через правый и левый индексы обхода дерева. Или СУБД поддерживает рекурсивную выборку. Или можно создать хранимую процедуру =]
        Ответить
        • Схема обычный ID, ParentID. Было CTE (SQL Server), там рекурсивно можно было получить всех детишек. И да это была хранимка.
          Ответить
          • Сам недавно занимался подобной хренью. Вот простой способ как это можно обойти
            http://www.rockstarapps.com/wordpress/?p=82
            Там нормально описаны выборки без вы%бонов.

            А вот псевдокод как легко создать дерево (если оно таки тебе понадобится).
            class TreeNode
            {
            void AddChild(TreeNode* child)
            void * data;
            }

            class SerializedNode
            {
            int thisId;
            int parentId;
            void * data;
            }


            TreeNode * BuildTree(SerializedNode* nodes[], int count)
            {
            hash_map<int, TreeNode *> insertedMap;
            TreeNode * root = new TreeNode();
            for (int i = 0; i != count; i++) {
            insertedMap.insert(nodes[i]->thisId, nodes[i]);
            if (0 == nodes[i]->parentId) {
            root.AddChild(nodes[i]);
            } else {
            insertedMap.find(nodes[i]->parentId).AddChild(nodes[i]);
            }
            }
            return root;
            }
            Ответить
            • Аха, суперсокое решение. Для того чтобы получить детишек, загружаем в память все данные(наприммер 10000 нод), строем дерево, а потом получаем 5 детишек. Мега.
              Ответить
              • Во-первых, это псевдокод для ВСЕГО дерева.
                Во-вторых, выборка следует быть с помощью средств СУБД. Хоть статью почитал?
                Ответить
      • так и есть хер знает скока джоинов. Оно один в один мапит.
        Ответить
    • ну, для неограниченной вложенности есть nested sets и прочие
      Ответить
    • Как минимум - отжег. Меня как-то больше радовало один Extension Method написать для рекурсивной выборки.
      Ответить
      • Что-то мне подсказывает, что екстеншем метод тут не поможет. Можеш код показать?
        Ответить
      • зато мегапроизводительно! :)
        Ответить
    • Говнище ))
      Интересно посмотреть на скрип которий линк сгенерит и пустит на сиквел.
      Ответить
      • джоины на каждый строку ;)
        Ответить
        • это пиздец)
          на самом деле деревянные данные достаточно часто трабл - обычно пишу хранимую процедуру и это правильно с точки зрения как читаемости кода, так и производительности - можно написать ее 1 раз и копипастить с минимальными изменениями для всех деревьев ;)
          Ответить

    Добавить комментарий