Autor Zpráva
slovakCZ
Profil
Dobrý den,
v první řadě omluvte diakritiku, mám nove mac a nevím jak si nastavit CZ klávesnici..

můj problém se dá jednoduše vysvětlit a napasovat na konkrétní příklad, tak to rovnou ukážu na něm. Pro začátek malá ilustrace:

http://awesomescreenshot.com/00627tozdb

jde mi o výpis produktů podle cenového rozpětí. To by nebylo nic tak složitého, ale problém mi tam dělají slevy. Je několik druhu (a kombinaci) slev. Důležitá informace je ta, že v databázi mám u produktů uloženou "základní cenu" a slevu vypočítávám až na straně PHP v aplikaci a to několika způsoby:

1) pokud v databázi u produktů je uložena procentuální nebo fixní cena, odečtu tuto cenu od základní ceny produktů

2) pokud má kategorie nastavenou slevu v procentech, všechny produkty v kategorii mají tuto slevu (případně se k ním připočte i sleva z bodů 1)

3) cenové skupiny uživatelů. Uživatel může být v cenové skupině, která má nastaven jistý koeficient, kterým se cena násobí. Při koeficientu menším než 1 jde o slevu (případně se této slevě připočte i sleva z bodů 2 (i 1))

takže mám produkt, který má v databázi uloženo toto:

zakladni_cena = 1000

sleva = 10%

zároveň je v kategorii, která má slevu 10%

a zároveň jsem přihlášen jako uživatel, který má na všechny produkty slevu 10%

dejme tomu, že mám tedy slevu 30%, takže produkt mě nestojí 1000, ale 700...

no a otázka tedy zní, jak sestavit takový SQL dotaz, který vybere produkty tak, aby zohledňoval i slevu? nemůžu sestavit něco takového:

SELECT * FROM produkt WHERE zakladni_cena > 800 AND zakladni_cena < 2000... sice mi to tento produkt vybere, ale aplikace vypočítá cenu na 700kc, což neodpovídá sql dotazů :o) dále chci mít samozřejmě zapojené stránkování, takže v dotazů budu mít i napr: LIMIT 20 a OFFSET 20...

nápad:

výběru všechny produkty bez ohledu na zadání cenového rozpětí. Tento výběr proženu v cyklu a v každém průchodu si vypočítám aktuální cenu pro daného uživatele a pokud tato cena bude odpovídat žádanému rozpětí, uložím si ID produktů do nějakého pole a poté už sestavím tento dotaz: SELECT * FROM produkt WHERE id IN $moje_pole_s_id_produktu LIMIT 20 OFFSET 20

vyřeší to problém, ale nezkoušel jsem to zatím, trochu se obávám toho zdvojení dotazů do databáze.. když se ptám jednou a výběru produkty, ty poté prozeny cyklem a následně sestavím finální dotaz... možná to bude pomalé při 10ti tisících produktů možná ne... napadá někoho lepší řešení?

děkuji moc
juriad
Profil
slovakCZ:
A nešlo by formulovat slevy už přímo v dotazu? Vždy, i při výpisu produku.
Nevím, však jak máš uložené slevy a kategorie, takže lépe neporadím.

Ten tvůj nápad má díry. Výsledek vyhledávání ve všech kategoriích chci setřídit podle ceny vzestupně, kde minimum je 100 Kč a maximum je 200 Kč.
V takovém případě bys nejen filtroval, ale i přehazoval pořadí produktů podle slev na kategorii a konkrétní produkt. Stránkování by bylo téměř nemožné (zobraz mi pátou stránku bez předchozí informace o produktech na prvních čtyřech stránkách).
okolojsoucí
Profil
slovakCZ:
v privni rade omluvte diakritiku
Neomluvíme, když už tak můžeš využít ohákování textu.

jak si nastavit CZ klavesnici
Věřím že si si přečetl manuál a když jsi selhal tak jsi nakoukl do strejdy gůgla
Krotíme českou klávesnici v OS X
Jak si změnit/nastavit klávesnici?
Jak přepnout klávesnici na českou
slovakCZ
Profil
juriad:
abych to tedy upřesnil:
databaze ma tyto tabulky (zjednodusim na potrebne veci):
- product
sloupce: id, category_id, price, discount_percent, discount_price
- category:
sloupce: id, discount
- customer:
sloupce: id, coefficient

takže jestli jsem to pochopil dobře, bylo by nejlepší sestavit už rovnou dotaz tak, aby si on sám na úrovni SQL vypočítal konečnou cenu produktů (takže zároveň se dotazů na to v jaké je kategorii, z ní výběru slevu, tu odečtu od ceny produktů, z php si do dotazů předám koeficient uživatele (jelikož až na úrovni php jsem schopen zjistit jeslti je uživatel přihlášeny), taktéž upravím cenu na základě koeficientu a následně zjistím slevu u produktů a tu také od ceny odečtu... jednoduše řečeno, sestavit na to pouze jeden dotaz, ve kterém bude X subdotazu a vyhnout se tomu mému navrhovanému resneni? je to správná cesta? :)


juriad
teoreticky by to strankovani nemel byt problem ne? zkusim pouvazovat:

// vyber vsech
$products = $db->product()->where('sklad > 0 AND zobraz_produkt = 1 AND category_id = 1')->order('price ASC');

// overeni cenoveho rozpeti
$produkty_co_souhlasi = array();
$cena_od = 200;
$cena_do = 1000;
foreach ($products as $product) {
    if($product['price'] >= $cena_od && $product['price'] <= $cena_do)
        $produkty_co_souhlasi[] = $product['id'];
}
$products = $db->product()->where('id IN ('. join(',', array_keys($products_match)) .')')->order('price ASC')->limit(10)->offset(30);

// v $products bych tedy mel mit produkty serazene podle ceny od 30 do 40. tedy nejakou 4. stranku vypisu... pokud se vratim na stranu 3. tak jen zmenit offset na 20...
juriad
Profil
Podle mě je to správná cesta, jen to omezení ceny bych ponechal a cenu násobil koeficientem zákazníka už v dotazu, ať je vysledkem vždy koncová cena pro konkrétního zákazníka (je jedno jestli přihlášeného nebo ne):

SELECT p.id,
  MIN(p.price * COALESCE(p.discount_percent, 1), p.price - COALESCE(p.discount_price, 0)) * COALESCE(c.discount, 1) * COALESCE(cu.coefficient, 1) final_price
  FROM product p
  JOIN category c ON p.category_id = c.id
  # pokud zákazník neexistuje, vlož hodnotu třeba -1 (left join se postará o to, že coefficient bude NULL)
  LEFT JOIN customer cu ON cu.id = $customer
  WHERE
    # pokud nefiltruje podle ceny, podmínku vůbec nedávej, nebo dej $min = 0 a $max = 1000000000
    MIN(p.price * COALESCE(p.discount_percent, 1), p.price - COALESCE(p.discount_price, 0)) * COALESCE(c.discount, 1) * COALESCE(cu.coefficient, 1) BETWEEN $min AND $max
  ORDER BY final_price # nebo řaď podle něčeho jiného
  LIMIT 20 OFFSET 20
slovakCZ
Profil
tak tohle asi az rano :) dekuju za nakopnuti, ono to asi bude jeste trochu slozitejsi, jelikoz produkt muze byt v nekolika kategoriich a v tom pripade se slevy z kategorii scitaji, takze si s tim zitra zkusim pohrat a snad to nejak pujde, zatim si ten dotaz moc neumim predstavit :), ale diky za nasmerovani.

takze v nejakem hardcore pripade to muze vypadat i takto:
produkt je ve 2 kategoriich a cele to je nataveno takto:
produkt: cena 1000, sleva 500kc
je v kategorii 1 a ta ma slevu 10%
je ale i v kategorii 2 a ta ma slevu 10%
uzivatel ma na cely eshop slevu 10%

vysledna sleva produktu je tedy 30% (a pote se odecte jeste 500kc) :o) vysledna cena je tedy 650kc.... no, bude to jeste zajimave :)
juriad
Profil
slovakCZ:
Pořádně si rozmysli pořadí a způsob aplikace slevy.
OK. Absolutní sleva musí být až poslední (mám to špatně).
Relativní slevy se nesčítají, ale násobí. Sleva tedy musí být 1 - 0.9 * 0.9 * 0.9 = 27.1 %
Pokud by produkt byl v jedenácti kategoriích a všechny měly slevu 10%, to bys to daleko nedotáhl... :)

S těmi výce kategoriemi to bude nepříjemné, budeš muset použít poddotaz pro výpočet celkové slevy z kategorií. Neexistuje agregační funkce, která umí násobit (obdoba SUM), budeš si muset pohrát s logaritmy a exponencielou.
slovakCZ
Profil
juriad:
v pohode, s tim uz si nejak poradim :) doufam.... to s temi slevami v kategoriich je opravdu neprijemne :) tak to je bohuzel navrzene a tak s tim uz lide pracuji takze se to menit nemuze.. to, ze nastavi v jedne kategorii slevu 70% a v druhe take 70% by melo byt osetreno tim, ze produkt se sice zobrazi, ale bez ceny a nelze jej koupit...

zatim diky moc a zitra rano se jeste pekne zapotim :)

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: