How to get Mysql SUM of multiple columns in database - php

I want to calculate total products in cart for one user by summing values for each product in cart.
I'm using this query :
SELECT *, SUM(quantity) OVER (PARTITION BY product_id ORDER BY id) AS TotalProducts
FROM cart WHERE user_id ='$user_id';
Getting error:
SQL syntax; check the manual that corresponds to your MariaDB server
version for the right syntax to use near '(PARTITION BY product_id
ORDER BY id)
EDIT with DB schema
id | product_id | quantity | user_id
1 | 37 | 2 | 23847
2 | 70 | 2 | 23847
I can't see what I'm doing wrong?

I'm not familiar with the MariaDB syntax, and you didn't show your schema, but here's my shot at an answer:
SELECT c.*,
SUM(c.quantity) as `TotalProducts`
FROM cart c
WHERE c.user_id = '$user_id'
GROUP BY c.user_id
Or, if you want a total per product, you could use:
SELECT c.*,
SUM(c.quantity) as `TotalProducts`
FROM cart c
WHERE c.user_id = '$user_id'
GROUP BY c.user_id, c.product_id

In MySQL, you can use a correlated subquery:
SELECT c.*,
(SELECT SUM(c2.quantity)
FROM cart c2
WHERE c2.user_id = c.user_id AND
c2.product_id = c.product_id AND
c2.id <= c.id
) as TotalProducts
FROM cart c
WHERE user_id = '$user_id';

Related

Finding the right count syntax in mySQL select statement

Goal:
To have a table of SIC codes with their descriptions (joined via another table) and count the number of instances of each DISTINCT SIC code used. Ideal outcome below...followed by current mySQL select statement:
SIC Code | Description | Count of SIC Code
0001 | Desc A | 10
0002 | Desc B | 50
000N | Desc N | 80
Current SQL Statement, but causing error notice:
$sql = "SELECT DISTINCT company_list.SIC_Codes, sic_codes.SIC_desc, COUNT(*) as sicCount, FROM company_list LEFT JOIN sic_codes ON company_list.SIC_Codes = sic_codes.SIC_code;";
Any ideas or perspective on which count syntax to use to obtain the example above?
Thank you.
Try making a subquery for COUNT something like this.
$sql = "SELECT DISTINCT company_list.SIC_Codes, sic_codes.SIC_desc, (SELECT COUNT(*) FROM company_list LEFT JOIN sic_codes ON company_list.SIC_Codes = sic_codes.SIC_code) as sicCount, FROM company_list LEFT JOIN sic_codes ON company_list.SIC_Codes = sic_codes.SIC_code";
Instead of putting the COUNT as field, try making a subquery for it.
Change COUNT(*) to (SELECT COUNT(*) FROM company_list LEFT JOIN sic_codes ON company_list.SIC_Codes = sic_codes.SIC_code)

MQL, PHP select all from two tables?

So i have two tables:
order_product
--------------------------------------------------
| ProductID | Quantity
--------------------------------------------------
products
-------------------------------------------------------------
| ProductID | productname | Desc | Price | Stock | Image
------------------------------------------------------------
and i need to get all of the same product ID, show their quantity then times that by their price and show the grand total of all.
My problem is i'm trying to show a checkout page which shows everything in a list, but how do i combine the two tables? Also, there are no foreign keys for the first table.
I need this in an sql statement as well preferably, like:
$sql = 'SELECT...'
Would this work?
$sql = "SELECT * FROM order_products
UNION
SELECT * FROM products"
If so, how do i know which row is which?
My desired output is all entries, now looking like this:
ProductID | Quantity | Productname | Desc | Price | Stock | Image
You need a classical JOIN clause:
SELECT *
FROM products
LEFT JOIN order_products on products.ProductId = order_products.ProductId
Not sure exactly what's the output you wish to get is but you should use something like this
SELECT o.ProductID, o.Quantity, p.Price, o.Quantity * p.Price
FROM order_product o
LEFT JOIN products p ON o.ProductID = p.ProductID
My problem is i'm trying to show a checkout page which shows
everything in a list, but how do i combine the two tables?
You need to simply use mysql JOIN to show cart items.
Your table data should be like as i added in demo.
See SQL Fiddle Demo
SELECT
o.id 'orderId',
o.ProductID 'pid',
SUM(o.Quantity) 'qty',
p.productname 'product',
p.`Price` 'price'
FROM
order_product o
INNER JOIN products p
ON p.`ProductID` = o.`ProductID`
Edit Required output
My desired output is all entries, now looking like this:
ProductID | Quantity | Productname | Desc | Price | Stock | Image
Modify above query's SELECT part SELECT tablename.your_column .....
Use inner join.
Select * from order_products op INNER JOIN products p ON p.ProductID = op.ProductID;
w.r.t. your need, the above query needs to be modified to:-
"SELECT *,
SUM(op.quantity * p.price) AS grandTotal
FROM order_products op
INNER JOIN PRODUCT p ON p.ProductID = op.ProductID WHERE p.ProductID =".$prodId(your php variable of product id);
select table1.ProductID
, table1.Quantity
, table2.Productname
, table2.Desc
, table2.Price
, table2.Stock
, table2.Image
FROM table1
JOIN table2 ON table1.productid=table2.productid

MySQL single insert using subquery rows as columns

How would I select 3 question IDs and use them as column data in for a single insert statement, using only MySQL.
I currently use the following statement to insert a new row into the game table by selecting a single random entry from the question table:
Current Table:
-------------------------------
| game | user_id | question_id |
-------------------------------
| 1 | 1 | 10 |
Current Statement:
INSERT INTO game (user_id, question_id)
SELECT u.id as user_id, q.id as question_id
FROM user u, question q
WHERE u.id =:uid
AND q.category = :category
ORDER BY RAND()
LIMIT 1
Game table:
I have added the columns opt_1-3 to allow for multiple choice
-------------------------------------------------------
| game | user_id | question_id | opt_1 | opt_2 | opt_3 |
-------------------------------------------------------
| 1 | 1 | 10 | 5 | 12 | 80 |
^ ^ ^
alternative wrong answers
I can achieve this with PHP, iterating over results and using two queries.
SELECT id FROM question
WHERE category = :category
ORDER BY RAND()
LIMIT 3
$opts = array();
foreach($result as $r){
$opts[] = $r->id;
}
INSERT INTO game (user_id, question_id)
SELECT u.id as user_id, q.id as question_id,
// add the following line to the query posted previously
$opt[0] AS opt_1, $opt[1] AS opt_2, $opt[2] AS opt_3
...
I want to know if its possible to achieve the same result purely using MySQL.
Not tested this much but this might do the job as the select for you.
Note that an order by rand() is not quick, and this involves a couple of cross joins which will also likely be slow if there are a large number of questions.
SELECT u.id as user_id, Sub1.aid, Sub1.bid, Sub1.cid
FROM user u,
(SELECT a.id AS aid, b.id AS bid, c.id AS cid
FROM question a, question b, question c
WHERE a.category = :category
AND a.category = :category
AND a.category = :category
AND a.id != b.id
AND a.id != c.id
AND b.id != c.id
ORDER BY RAND()
LIMIT 1) Sub1
WHERE u.id =:uid

Display only the newest record for each row in MySQL db using PHP

I have two tables of which one is updated daily. I would like to display "only" the latest record for each row.
This is the query I am using now that of course returns all the records.
SELECT *
FROM ss_pumps, secondary_systems WHERE ss_pumps.id=secondary_systems.segment_id
ORDER BY id ASC
Any help would be greatly appreciated!
You can find the latest record for every segment_id by ID using subquery. The result of the subquery is then join against the two tables: ss_pumps and secondary_systems.
SELECT a.*, c.*
FROM ss_pumps a
INNER JOIN
(
SELECT segment_id, MAX(datefield) max_val
FROM secondary_systems
GROUP BY segment_id
)b ON a.id = b.segment_id
INNER JOIN secondary_systems c
ON b.segment_id = c.segment_id AND
b.max_val = c.datefield
Actually, I'm not sure how your tables: ss_pumps and secondary_systems are related with each other.
I think you want it the other ways,
SELECT a.*, b.*
FROM secondary_systems a
INNER JOIN ss_pumps b
ON a.segment_ID = b.segment
INNER JOIN
(
SELECT segment, MAX(ID) max_val
FROM ss_pumps
GROUP BY segment
) c ON b.segment = c.segment AND
b.ID = c.max_val
Use this query:
SELECT * FROM ss_pumps, secondary_systems WHERE ss_pumps.id=secondary_systems.segment_id ORDER BY id DESC LIMIT 1
This is assuming that id is an auto increment column and will always be inserted in order.
Here's what I got:
SELECT *
FROM
ss_pumps ssp
LEFT JOIN ( SELECT * FROM secondary_systems ORDER BY id DESC ) ss ON ( ssp.id = ss.segment_id )
GROUP BY
ssp.id
ORDER BY
ssp.id ASC
CAVEAT: I'm assuming that the secondary_systems has its own id field that also autoincrements. That's the only way you can make sure you're getting "only" the latest record for each row.
Demo: http://sqlfiddle.com/#!2/f816b/2/0
In my demo ss_pumps held the parents while secondary_systems held the children. Each parent has 3 children. All but the last children are boys. The last child is always a girl. According to your problem, the resulting query should yield only girls.
| ID | PARENT | SEGMENT_ID | CHILD |
------------------------------------
| 1 | mother | 1 | betty |
| 2 | father | 2 | tina |

Tough Mysql Query

I got a skill test for a quick mysql query. I am given the tables:
Orders OrderItems
----------------------------------------
id id
date order_id(Orders.id)
shipping_amount product_id
order_status price
customer_id quantity
I need to show Orders id and totals (including shipping amount) and records prior to June 1, 2003.
output should be...
| OrderID | OrderTotal |
+-----------+------------+
| 13230 | $55.00 |
| 54455 | $40.00 |
| 59694 | $33.04 |
| 39495 | $21.05 |
The hint is to use Group by or subselect. I have the following statement so far but not sure what to do next.
Select id AS OrderId,***(not sure what to do here)
from Orders join OrderItems on Orders.id=OrderItems.id
I don't have access to a mysql database to test, but I would imagine it looks something like this:
select
o.id OrderID,
(select sum(oi.price * oi.quantity) from order_items oi where oi.order_id = o.id) + o.shipping_amount OrderTotal
from
orders o
where
o.date < str_to_date('2003-06-01', '%Y-%m-%d');
I'd say it must look like this:
SELECT O.ID as OrderID, SUM(OI.price * OI.quantity) AS OrderTotal
FROM Orders O
INNER JOIN OrderItems OI ON O.id = OI.order_Id
WHERE date < '2003-06-01'
GROUP BY O.id
ORDER BY SUM(price * quantity) DESC
Not sure how to format dates in MySQL though or if you can order by an agregate function in this version but I'm pretty sure this is a good start.

Categories