إنشاء استعلام SQL أن أوامر النتائج التي بشرط الوفاء

StackOverflow https://stackoverflow.com/questions/475178

  •  19-08-2019
  •  | 
  •  

سؤال

هذا هو MySQL و PHP

لدي جدول يحتوي على الأعمدة التالية:

navigation_id (unsigned int primary key)
navigation_category (unsigned int)
navigation_path (varchar (256))
navigation_is_active (bool)
navigation_store_id (unsigned int index)

البيانات سيتم شغلها مثل:

1, 32, "4/32/", 1, 32
2, 33, "4/32/33/", 1, 32
3, 34, "4/32/33/34/", 1, 32
4, 35, "4/32/33/35/", 1, 32
5, 36, "4/32/33/36/", 1, 32
6, 37, "4/37/", 1, 32
... another group that is under the "4/37" node
... and so on

لذلك هذا سوف تمثل شجرة مثل هيكل.هدفي هو كتابة استعلام SQL أنه نظرا تخزين معرف 32 و فئة معرف 33, سيعود

أول مجموعة من العناصر الآباء من فئة 33 (في هذه الحالة 4 و 32)

ثم مجموعة من العناصر طفل من الفئة 33 (في هذه الحالة ، 34 ، 35 ، 36)

ثم بقية "الجذر" فئات الفئة 4 (في هذه الحالة 37).

لذا الاستعلام التالي سيعود النتائج الصحيحة:

SELECT * FROM navigation 
WHERE navigation_store_id = 32 
AND (navigation_category IN (4, 32) 
    OR navigation_path LIKE "4/32/33/%/" 
    OR (navigation_path LIKE "4/%/" 
        AND navigation_category <> 32))

مشكلتي هي أنني أريد أن تأمر "مجموعات" من الفئات في النظام المذكورة أعلاه (الآباء 33 أولا ، الأطفال من 33 ثانية ، والآباء والأمهات من عقدة الجذر الماضي).حتى إذا استوفت الشرط الأول ، طلب منهم أولا ، إذا استوفت الشرط الثاني ترتيبها الثانية وما إذا كانت تفي الثالث (أو الرابع) حالة ترتيبها الماضي.

يمكنك ان ترى مثالا على كيفية فئة هيكل يعمل في هذا الموقع:

www.eanacortes.net

قد تلاحظ أنه بطيئة إلى حد ما.الطريقة الحالية أنا أفعل هذا أنا باستخدام الماجنتو الأصلي الفئة الجدول وتنفيذ ثلاثة بطيئة بشكل خاص الاستفسارات على ذلك ؛ ثم وضع النتائج معا في PHP.باستخدام هذا الجدول الجديد أنا حل مسألة أخرى لدي مع الماجنتو ولكن أيضا تحسين أدائي في نفس الوقت.أفضل طريقة أرى هذا يجري إنجازه هو وضع كل ثلاثة استفسارات معا وبعد PHP العمل أقل من خلال وجود نتائج فرز بشكل صحيح.

شكرا

تحرير

حسنا, يعمل كبيرة الآن.اقطعها من 4 ثوان وصولا إلى 500 السيدةبسرعة كبيرة الآن :)

هنا هو بلدي رمز في Colleciton الدرجة:

    function addCategoryFilter($cat)
    {
        $path = $cat->getPath();
        $select = $this->getSelect();
        $id = $cat->getId();
        $root = Mage::app()->getStore()->getRootCategoryId();
        $commaPath = implode(", ", explode("/", $path));

        $where = new Zend_Db_Expr(
            "(navigation_category IN ({$commaPath}) 
                    OR navigation_parent = {$id}
                    OR (navigation_parent = {$root}
                    AND navigation_category <> {$cat->getId()}))");

        $order = new Zend_Db_Expr("
                CASE
                    WHEN navigation_category IN ({$commaPath})  THEN 1
                    WHEN navigation_parent = {$id} THEN 2
                    ELSE 3
                END, LENGTH(navigation_path), navigation_name");

        $select->where($where)->order($order);
        return $this;
    }

ثم تستهلك التعليمة البرمجية التالية في فئة كتلة:

        // get our data
        $navigation = Mage::getModel("navigation/navigation")->getCollection();
        $navigation->
            addStoreFilter(Mage::app()->getStore()->getId())->
            addCategoryFilter($currentCat);

        // put it in an array
        $node = &$tree;
        $navArray = array();
        foreach ($navigation as $cat)
        {
            $navArray[] = $cat;
        }
        $navCount = count($navArray);

        $i = 0;

        // skip passed the root category
        for (; $i < $navCount; $i++)
        {
            if ($navArray[$i]->getNavigationCategory() == $root)
            {
                $i++;
                break;
            }
        }

        // add the parents of the current category
        for (; $i < $navCount; $i++)
        {
            $cat = $navArray[$i];

            $node[] = array("cat" => $cat, "children" => array(), 
                "selected" => ($cat->getNavigationCategory() == $currentCat->getId()));
            $node = &$node[0]["children"];

            if ($cat->getNavigationCategory() == $currentCat->getId())
            {
                $i++;
                break;
            }
        }

        // add the children of the current category
        for (; $i < $navCount; $i++)
        {
            $cat = $navArray[$i];
            $path = explode("/", $cat->getNavigationPath());
            if ($path[count($path) - 3] != $currentCat->getId())
            {
                break;
            }

            $node[] = array("cat" => $cat, "children" => array(), 
                "selected" => ($cat->getNavigationCategory() == $currentCat->getId()));
        }

        // add the children of the root category
        for (; $i < $navCount; $i++)
        {
            $cat = $navArray[$i];
            $tree[] = array("cat" => $cat, "children" => array(), 
                "selected" => ($cat->getNavigationCategory() == $currentCat->getId()));
        }

        return $tree;

إذا أنا يمكن أن تقبل إجابتين أقبل الأولى و الأخيرة, و إذا أنا يمكن أن تقبل إجابة بأنها "مثيرة للاهتمام/مفيدة" أود أن تفعل ذلك مع الثانية.:)

هل كانت مفيدة؟

المحلول

A CASE التعبير ينبغي أن تفعل خدعة.

SELECT * FROM navigation 
    WHERE navigation_store_id = 32 
        AND (navigation_category IN (4, 32) 
            OR navigation_path LIKE "4/32/33/%/" 
            OR (navigation_path LIKE "4/%/" 
            AND navigation_category <> 32))
    ORDER BY
        CASE
            WHEN navigation_category IN (4, 32) THEN 1
            WHEN navigation_path LIKE "4/32/33/%/" THEN 2
            ELSE 3
        END, navigation_path

نصائح أخرى

محاولة إضافية مشتقة عمود مثل "الوزن":

(لم تختبر)

(IF(criteriaA,1,0)) + (IF(criteriaB,1,0)) ... AS weight
....
ORDER BY weight 

كل المعايير زيادة "الوزن" من هذا النوع.يمكنك أيضا تعيين الأوزان واضح من قبل التعشيش شروط إعطاء المجموعات معين صحيح إلى نوع من مثل:

IF(criteriaA,0, IF(criteriaB,1, IF ... )) AS weight

لا MySQL لديك UNION SQL الكلمة الجمع بين الاستفسارات?ثلاث استفسارات أساسا غير متداخلة معايير لذا أظن أنه من الأفضل أن تترك لهم أساسا منفصلة الاستعلامات, ولكن الجمع بينهما باستخدام UNION أو UNION ALL.هذا سيوفر 2 DB ذهابا وإيابا ، وربما تجعل من الأسهل بالنسبة الخلية الاستعلام مخطط "رؤية" أفضل طريقة للعثور على كل مجموعة من الصفوف.

بالمناسبة الاستراتيجية الخاصة بك من يمثل شجرة عن طريق تخزين مسارات من الجذر إلى الحافة من السهل متابعة وإنما الكفاءة كلما كنت في حاجة إلى استخدام جملة WHERE من شكل navigation_path like '%XYZ' - على كل DBs رأيت ، LIKE يجب أن تبدأ مع غير بدل لتمكين استخدام مؤشر على هذا العمود.(في المثال التعليمات البرمجية المتكررة, كنت بحاجة إلى مثل هذا البند إذا كنت لا تعرف بالفعل أن جذور الفئة 4 (كيف عرفت ذلك ؟ من منفصلة في وقت سابق query؟))

كيف وغالبا ما الفئات التغيير ؟ إذا كانوا لا تغيير في كثير من الأحيان ، يمكن أن تمثل شجرة الخاص بك باستخدام "مجموعات متداخلة" الأسلوب هو موضح هنا, التي تمكن أسرع بكثير استفسارات عن أشياء مثل "ما هي فئات أحفاد/الأجداد من فئة معينة".

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top