SQL sorgu oluşturma onlar karşılamak hangi koşul tarafından emir sonuçları

3 Cevap php

Bu MySQL ve PHP için

Ben aşağıdaki sütunları içeren bir tablo var:

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

Veri gibi dolu olacaktır:

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

Yani bu yapısı gibi bir ağaç temsil edecek. Amacım, 33 32 ve kategorisi ID mağaza kimliği verilen dönecektir bir SQL sorgusu yazmak için

İlk olarak, bir (bu örnekte 4 ve 32), kategori 33 anne elemanlarının grubu

Daha sonra, (bu durumda 34, 35, ve 36) kategori 33 bir çocuk vardır elemanlarının bir grubudur

Sonra (bu durumda 37) kategorisi altında 4 "kök" kategorilerinde kalanı.

Yani aşağıdaki sorgu doğru sonuçları dönecektir:

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))

Benim sorunum yukarıda listelenen sırayla kategoride "grupları" (ilk 33 anne, 33 saniye çocukları ve son kök düğümün anne) sipariş etmek istiyor. Onlar ilk koşulu karşılamak Yani, onlar üçüncü (ve dördüncü) durumu Düzende onları karşılamak durumunda en son onlar ikinci, ikinci koşul Düzende onları karşılamak durumunda, onları ilk sipariş ve.

Sen kategori yapısı bu sitede nasıl çalıştığını bir örnek görebilirsiniz:

www.eanacortes.net

Bunu oldukça yavaş olduğunu fark edebilirsiniz. Ben Magento'nın orijinal kategori tablosunu kullanarak ve bunun üzerine üç özellikle yavaş sorguları yürütme olduğum bu yapıyorum geçerli yolu; Daha sonra PHP araya sonuçları koyarak. Bu yeni tablo kullanarak ben magento var ama aynı zamanda benim performansını artırmak istiyorum başka bir sorunu çözme duyuyorum. Ben bu başarılı olmanın görmek iyi yolu birlikte her üç sorguları koyarak ve düzgün sıralanmış sonuçlara sahip PHP çalışma daha az yaşıyor.

Teşekkürler

EDIT

Tamam, şimdi harika çalışıyor. Aşağı 500 MS 4 saniye aşağı kesti. Şimdi büyük hız :)

İşte koleksiyonunda sınıfında benim kod:

    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;
    }

Sonra benim Kategori blokta bulunan aşağıdaki kodla tüketmek:

    	// 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;

If I could accept two answers I would accept the first and last one, and if I could accept an answer as "interesting/useful" I would do that with the second. :)

3 Cevap

A CASE ifadesi hile yapmak gerekir.

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

"Ağırlık" gibi bir ek türetilmiş sütun deneyin:

(untested)

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

Each criteria increases the "weight" of the sort. You could also set the weights distinctly by nesting IFs and giving the groups a particular integer to sort by like:

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

MySQL sorguları birleştirmek için UNION SQL anahtar kelime var mı? Sizin üç sorguları esas örtüşmeyen kriterleri var, bu yüzden esas olarak ayrı sorguları onlara bırakmak en iyisi şüpheli, ama UNION veya UNION ALL kullanarak onları birleştirir. Bu 2 DB yuvarlak geziler kaydedebilirsiniz, ve muhtemelen daha kolay MySQL sorgu planlayıcısı her satır kümesini bulmak için en iyi yolu "görmek" için yapacaktır.

Eğer formun bir WHERE yan tümcesi kullanmak için navigation_path like '%XYZ' gerektiğinde arada, kökten uca yolları saklayarak ağacı temsil strateji takip etmek kolay ama oldukça verimsiz - ben tüm veritabanları üzerinde görülen, LIKE koşulları bu sütunun üzerinde bir dizin kullanımını etkinleştirmek olmayan bir joker karakter ile başlamalıdır. (Zaten kök kategori 4 olduğunu bilmiyordum eğer örnek kod parçacığını, sen nasıl bu arada? Ayrı, önceki sorguda?) Bilmiyordu (böyle bir madde gerekir)

Ne kadar sıklıkla kategoriler değiştirebilirim? Genellikle değiştirmek istemiyorsanız, size "bir kategori torunları / ataları Hangi kategoriler vardır" gibi şeyler üzerinde çok daha hızlı sorgular sağlayan açıklanan "iç içe setleri" yöntemi, here, kullanarak ağaç temsil edebilir .