Chceš rozjet Affiliate? Tak jedině v CJ.com, technologii využívá iDnes.cz, Denik.cz i SME.sk
Zobrazují se odpovědi 1 až 3 z 3

Získání kategorií výrobku z DB

  1. Poulik Hodnocení: 1 (100%) Poulik je na dobré cestě
    1
    Dobrý den,
    námět na diskuzi mě osobně velice zaujal, tak přidávám tento příspěvek.
    Kód řeší tuto situaci: v databázi jsou u výrobku uložené kategorie, u každé položky jich je více a jsou odděleny čárkou (např. "sport, zdravá výživa, ..."). Potřeboval jsem získat seznam jednotlivých kategorií od všech výrobků a jejich počet. Věřím, že by to šlo udělat lépe, avšak zde je moje řešení:
    Kód:
    $db = connect();
    $v = mysql_query("SELECT category FROM product order by category");
    $arr = array();
    
    while ($r = mysql_fetch_assoc($v))
       $arr[] = explode(",", $r['category']);
    
    $r = array();
    foreach ($arr as $v) {
       foreach ($v as $name) {
          $k = array_keys($r);
          $name = trim(mb_strtolower($name, "utf8"));
          $r[$name] = in_array($name, $k) ? ++$r[$name] : 1;
       }
    }
    mysql_close($db);
    výsledek tedy poté vypadá takto
    Kód:
    $r - array("sport"=>1, "xxx"=>10, ...);
    snad se bude hodit;).
    Pozn.: Zajímalo by mě, jestli to lze udělat přímo v databázi, chvíli jsem něco zkoušel, ale pak jsem zvolil cestu php...
    Naposledy upravil Poulik : 05.06.2011 v 19:01

  2. Co se právě děje na Webtrhu?
  3. Díky za odvážný první příspěvek do nové sekce.

    Největší slabinou tohoto řešení je struktura databáze. Ukládáním kategorií jako výrazů oddělených speciálním znakem se obíráte o všechny funkce relační databáze.
    Na vašem místě bych databázi denormalizoval, tj. vytvořil strukturu naznačenou tady:

    Kód:
    CREATE TABLE product (
        `productid` INT UNSIGNED NOT NULL,
        ...
    )
    CREATE TABLE category (
        `categoryid` INT UNSIGNED NOT NULL,
        ...
    )
    CREATE TABLE product_category (
        `productid` INT UNSIGNED NOT NULL,
        `categoryid` INT UNSIGNED NOT NULL
    )
    Seznam kategorií, počet kategorií, počet výrobků v kategorii atd. pak dostanete triviálními SQL dotazy.
    Kód:
    SELECT * FROM category;
    SELECT COUNT(*) AS categoryCount FROM category;
    SELECT COUNT(*) AS productCount FROM product_category GROUP BY categoryid;
    Předpokládejme ale, že z nějakého důvodu není možné jména normalizovat. Třeba počítáme frekvenci slov v textu.
    Moje verze je tady:
    Kód:
    $queryResult = mysql_query("SELECT category FROM product order by category");
    while ($row = mysql_fetch_assoc($queryResult)) {
        $categories = explode(",", $row['category']);
        foreach ($categories as $category) {
            $normalizedName = normalizeName($category);        
            if( ! isset($frequencyTable[$normalizedName])) {
                $frequencyTable[$normalizedName] = 1;
            } else {
                $frequencyTable[$normalizedName] += 1;
            }
        }
    }
    
    function normalizeName($name) {
        $normalized = mb_strtolower($name);
        $normalized = trim($normalized);
        return $normalized;
    }
    Hlavní problém kódu jsou názvy proměnných.
    Jednopísmenné proměnné nemají v kódu co dělat a navíc stejná proměnná má na různých místech odlišnou funkci ($v, $r).

    Je zbytečné řadit v SQL dotazu kategorie podle abecedy. Řazení v tomto případě nehraje roli.

    Blok po while() by měl být obalený složenými závorkami, ačkoliv má jen jeden řádek.

    Když budeme frekvenci počítat už v cyklu, ve kterém procházíme řádky z DB, ušetříme jeden foreach() průchod.

    V každém cyklu provádíte zbytečně náročnou operaci array_keys() a následně in_array(). Stačí se zeptat na existenci klíče.

    Díky za kód a jsem zvědavý, co napadne ostatní.

  4. Poulik Hodnocení: 1 (100%) Poulik je na dobré cestě
    3
    Děkuji za rychlou odpověď,
    bohužel databázi nelze udělat jinak.
    Proměnné jsem nezvolil zcela dobře, u cyklů, které neobsahují více než jeden příkaz jsem zvyklý nedělat závorky, i když to někdy znepřehledňuje kód. Děkuji za upozornění, že provádím zbytečně operace array_keys() a následně in_array(), někdy na jednoduchých věcích hledám složitosti, když to jde udělat jednuduše pomocí isset:)
    Dát foreach přímo do whilu mě taky nenapadlo - další poučení...:[ Příště už se snad takovýchto chyb vyhnu...:)

Hostujeme u Server powered by TELE3