إنشاء استعلام SQL أن أوامر النتائج التي بشرط الوفاء
سؤال
هذا هو 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؟))
كيف وغالبا ما الفئات التغيير ؟ إذا كانوا لا تغيير في كثير من الأحيان ، يمكن أن تمثل شجرة الخاص بك باستخدام "مجموعات متداخلة" الأسلوب هو موضح هنا, التي تمكن أسرع بكثير استفسارات عن أشياء مثل "ما هي فئات أحفاد/الأجداد من فئة معينة".