Sumowanie produktów z koszyka

0

Hi,
wymyśliłem sobie sumowanie produktów z mojego koszyka, tylko, że mam pewien problem, bo albo za bardzo kombinuję albo źle zaprojektowałem kilka tabel. Może na początek przedstawie strukturę tabel:

Tabela z koszykiem:

CREATE TABLE `basket` (
  `id_product_basket` int(11) NOT NULL,
  `member_id` int(11) NOT NULL,
  `product_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Do tej tabeli dołączam jeszcze:

CREATE TABLE `members` (
  `id_user` int(11) NOT NULL,
  `username` varchar(24) NOT NULL,
  `password` varchar(50) NOT NULL,
  `email` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `products` (
  `id_product` int(11) NOT NULL,
  `category_id` int(11) NOT NULL,
  `product_name` text NOT NULL,
  `product_price` decimal(10,2) NOT NULL,
  `product_status` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `promo` (
  `id_promo` int(11) NOT NULL,
  `product_id` int(11) NOT NULL,
  `percent_promo` int(3) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Moje aktualne zapytanie:

$getDataInBasket2 = $db->prepare("SELECT a.id_product, a.product_price, b.percent_promo FROM `products` AS `a` 
					JOIN `promo` AS `b` ON a.id_product = b.product_id
					JOIN `basket` AS `c` ON a.id_product = c.product_id
					JOIN `members` AS `d`
					WHERE `id_user` = :member_id
			    	");
$getDataInBasket2->bindValue(":member_id", $_SESSION['id_user'], PDO::PARAM_INT);
if(!$getDataInBasket2->execute()){
        print_r($getDataInBasket2->errorInfo());
}

trochę tego dużo ale już tłumaczę jak to ma działać. Chodzi o zsumowanie wszystkich produktów z koszyka z uwzgędnieniem promocji dlatego też łączę z tabelą promo. W tabeli promo jest procent promocji na podstawie, którego "w locie" obliczam ile wynosi aktualna cena, kodem:

$resultOfPromo = $basketContainer2['product_price'] / 100 * $basketContainer2['percent_promo'];
$newPrice = $basketContainer2['product_price'] - $resultOfPromo;

Na podstawie pobranej ceny normalnej oraz procentu promocji powinna się wyświetlić cena promocyjna.
Aktualne zaptanie, co prawda wyświeetla cenę produktu ale tylko pierwszego z koszyka. Nie sumuje.
Jeśli ktoś się w tym połapie oraz byłby w stanie mi pomóc jak zliczyć wszystkie produkty z koszyka z uqzględnieniem promocji to będę bardzo wdzięczny.
Pozdrawiam.

0

masz źle zaprojektowane tabele. Co jest nie tak:
0. (kosmetyczne) nie podobają mi się nazwy - nazwy PK wyglądają dziwnie i inaczej niż nazwy FK, tabela members a klucz id_user, percent_promo taka świnka morska - może np. discount, pole id_product_basket też dziwne, nieprzystające do innych

  1. gdzie masz ilość danego towaru w koszyku?
  2. dziwna ta promocja bo wg Twojego zapytania może być tylko jedna na dany towar
  3. w zapytaniu o koszyk nie potrzebujesz w ogóle tabeli members
  4. od tego masz SQLa aby takie rzeczy jak np. cena końcowa wyliczać w zapytaniu
select
  p.id_product,
  p.product_price, 
  r.percent_promo,
  round(p.product_price * (1 - coalesce(r.percent_promo, 0) / 100), 2) end_price
from
  basket b
  join products p on p.id_product = b.product_id
  left join promo r on r.product_id = b.product_id
where
  b.member_id = 1
0
abrakadaber napisał(a):

masz źle zaprojektowane tabele. Co jest nie tak:
0. (kosmetyczne) nie podobają mi się nazwy - nazwy PK wyglądają dziwnie i inaczej niż nazwy FK, tabela members a klucz id_user, percent_promo taka świnka morska - może np. discount, pole id_product_basket też dziwne, nieprzystające do innych

  1. gdzie masz ilość danego towaru w koszyku?
  2. dziwna ta promocja bo wg Twojego zapytania może być tylko jedna na dany towar
  3. w zapytaniu o koszyk nie potrzebujesz w ogóle tabeli members
  4. od tego masz SQLa aby takie rzeczy jak np. cena końcowa wyliczać w zapytaniu
  1. Tak, wiem miałem to zmmienić, było na szybko robione bez wchodzenia w szczegóły.
  2. Nie wiem czy dobrze to robię ale ilość towaru liczę zapytaniem przy pomocy COUNT, w ten sposób:
$getDataInBasket = $db->prepare("SELECT COUNT(`id_product_basket`) AS `countBasket` FROM `basket` WHERE `member_id` = :member_id");
$getDataInBasket->bindValue(":member_id", $_SESSION['id_user'], PDO::PARAM_INT);
if(!$getDataInBasket->execute()){
     print_r($getDataInBasket->errorInfo());
}else{
 	$basketContainer = $getDataInBasket->fetch();
	$getDataInBasket = $basketContainer['countBasket'];	
}
  1. Dlaczego dziwna promocja? Promocja na dany produkt, co w tym dzwnego?
  2. Tak, masz rację.
  3. Nie do końca działa tak jak powinno. Twój kod zwraca po prostu cenę ostatniego produktu no chyba, że źle może zrozumiałem?
0

Punkt 4 cofam, zapomnaiłem o SUM() :)

W ten sposób to rozwiązałem:

SELECT
	 p.id_product,
	 p.product_price, 
	 r.percent_promo,
	 SUM(round(p.product_price * (1 - COALESCE(r.percent_promo, 0) / 100), 2)) end_price
	FROM
	basket b
	JOIN products p ON p.id_product = b.product_id
	LEFT JOIN promo r ON r.product_id = b.product_id
	WHERE
	b.member_id = :member_id

Tak trochę odchodząc od tematu, pewnie zauważłeś, że mam pewien problem z nazewnictwem tych wszystkich zmiennych. Czy mógłbyś rzucić jakimś przykładem jak byś ty nazwał te zmienne w odniesieniu do powyższego kodu PHP?

0

Co chcesz dostać w wyniku tego zapytania bo ja nie do końca rozumiem. Chcesz mieć ilość WSZYSTKICH towarów i SUMĘ ich wartości?
A teraz zastanów się jak zapiszesz w bazie taki przypadek: 10 szt towaru x, 15 szt towaru y i 3 szt towaru z.

Co do nazewnictwa to z PHP Ci nie pomogę bo to nie moja bajka. Co do SQL to ja preferuję tak:

  1. nazwy tabel w liczbie pojedynczej
  2. pole PK po prostu id
  3. pole FK nazwa tabeli do której się odnosi + _id. W szczególnych przypadkach (np. odwołanie się kilka razy do tej samej tabeli) nazwa pola FK kojarząca się z funkcją pola
  4. niepotrzebnie poprzedzasz nazwy pól nazwą tabeli, np. product_price w tabeli products
  5. nazwy składające się z wielu członów oddzielone _ zamiast np. camelCase czy PascalCase
    ale przede wszystkim trzymanie się jednej obranej konwencji
0

Odnośnie tego co powiedziałeś o tych produktach to doałem sobie do tabeli basket koumnę amount w której gromadzę liczbę produktów. Obok przycisku "Dodaj do koszyka" zrobiłem numeryczny input, dzięki któremu dodaję ilość danych produktów do koszyka. I to mi wszystko działa. No prawie wszystko. Problem pojawił się znów pry sumowaniu. Co prawda sumuje mi wszystkie produkty tak jak ma tylko, że zawsze w ostatecznej cenie walnie się o 1 grosz.

Zapytanie:

SELECT p.id_product, p.product_price, r.percent_promo,
SUM(round(b.amount * p.product_price * (1 - COALESCE(r.percent_promo, 0) / 100), 2)) end_price
FROM basket b
JOIN products p ON p.id_product = b.product_id
 LEFT JOIN promo r ON r.product_id = b.product_id
WHERE
b.member_id = :member_id

Dlaczego tak się dzieje?

0

Produkty bez promocji sumują się ok natomast przy produktach promocyjnych cena zawsze jest mniejsza o 1 grosz. Dlaczego?

0

bez przykładowych danych nikt nic Ci nie odpowie.

0
abrakadaber napisał(a):

bez przykładowych danych nikt nic Ci nie odpowie.

Ok, załączam strukturę bazy danych oraz przykładowe dane. Jakbyś mógł rzucić okiem na to czemu mi te grosze giną było by super, bo mnie się już pomysły skończyły.

0

http://sqlfiddle.com/#!9/f77d95/8

poszczególne wartości

 648.25
 430.36
 247.00
----------
1325.61

a ile wg Ciebie powinno być?

1 użytkowników online, w tym zalogowanych: 0, gości: 1