I want to make a "best sellers" list using information from previous orders. What I currently have is something like this;
Product Quantity
2227 30
1722 3
1851 7
2227 10
1722 4
1863 1
etc....
The first column (product) is the unique ID in the database for each product. The quantity is of course how many items have been sold. Each row is for one order. So the ID 2227 appears two times on this list.
How can I sort this data so that I get a total of how many times ID 2227 is sold?
My PHP at the moment is:
$SQL_best = "SELECT c.company, co.id, cod.productId, cod.quantity
FROM customers c
LEFT JOIN customers_orders co ON c.id = co.custId
LEFT JOIN customers_orders_details cod ON co.id = cod.orderId
WHERE c.reseller =1
AND c.status != 99
AND c.id = ".$intCustomerId;
$result_best = $objDB->sqlExecute($SQL_best);
*some html code here*
<table style="margin:0px auto;">
<tr>
<th>Product</th>
<th>Quantity</th>
</tr>
<?php
while($obj_best = $objDB->getObject($result_best)) {
if ($obj_best->quantity > 0) { // don't include negatve quantaties (RMA's / refunds)
echo "<tr>";
echo "<td>".$obj_best->productId."</td>";
echo "<td>".$obj_best->quantity."</td>";
echo "</tr>";
}
}
?>
</table>
MySQL query
So I need to add together all the $obj_best->productId´s. How do I do that in this case? Or should I be editing my query?
This is an idea, you change the SQL string like this:
$SQL_best = "SELECT c.company, co.id, cod.productId,
SUM(cod.quantity) AS quantity
FROM customers c
LEFT JOIN customers_orders co ON c.id = co.custId
LEFT JOIN customers_orders_details cod ON co.id = cod.orderId
WHERE c.reseller = 1
AND c.status != 99
AND c.id = " . $intCustomerId . "
GROUP BY cod.productId
HAVING quantity > 0
ORDER BY quantity DESC";
Related
I'm trying to group sql results with the same product_id and count how many of the are there of each
I this photo you can see that I have 4 sales with the same product_id.
id product_id qty price date user
37 50 1 9.90 2018-09-29 1
31 50 1 9.90 2018-09-29 6
32 50 1 9.90 2018-09-29 6
38 50 1 9.90 2018-09-29 1
Current query:
SELECT
s.id,
s.qty,
s.price
FROM
sales s
LEFT JOIN products p ON
s.product_id = p.id
ORDER BY
s.date
DESC
PHP:
<?php foreach ($sales as $sale):?>
<tr>
<td class="text-center"><?php echo count_id();?></td>
<td><?php echo remove_junk(htmlspecialchars_decode($sale['name'])); ?></td>
<td class="text-center"><?php echo (int)$sale['qty']; ?></td>
<td class="text-center"><?php echo remove_junk($sale['price']);?></td>
</tr>
<?php endforeach;?>
Basically going form a to b like in the photo, without merging them into one row
Edited to provide a better explanation (Edited again for product_id mistake):
You should use a GROUP statement to group the results by product ID. With a group statement, you can then SUM the value of the quantity column. If you choose you can group by only the product ID, but then the date would be meaningless because all the items with that product ID would be grouped with the date of just one of them. Since you included the date in your result set, it seems that that is an important element of what you're trying to show.
The following code would GROUP BY both product ID and date, which would show you how many of each product were purchased on each date.
SELECT
s.product_id,
SUM(s.qty),
s.price
FROM
sales s
LEFT JOIN products p ON
s.product_id = p.id
GROUP BY s.product_id, s.date
ORDER BY
s.date
DESC
How can I combine 3 tables in a INNER JOIN?
The end result I am after is getting a list of CATEGORIES belonging to a PRODUCT - including the CATEGORY'S PARENT ID CATEGORY value (ie: Sneakers and Nike).
The CATEGORIES table and PRODUCTS table are joined in the PRODUCTS & CATEGORIES table. A product can belong to many categories and a category can have many products.
Here's more-or-less the setup I have in my database...
CATEGORIES TABLE:
CAT ID | PARENT ID | CATEGORY
1 | 0 | Sneakers
2 | 1 | Nike
3 | 2 | Jordan
PRODUCTS TABLE:
PROD ID
1
2
3
PRODUCTS & CATEGORIES TABLE:
CAT ID | PROD ID
1 | 0
1 | 1
2 | 3
I am running these queries and I am getting some results, but at the moment I am running 2 separate queries...
$q1 = "SELECT prodid, GROUP_CONCAT(catid SEPARATOR ' // ') as catid FROM products_categories group by prodid order by prodid";
$result1 = $conn->query($q1);
if ($result1->num_rows > 0) {
while($prods = $result1->fetch_assoc()) {
echo "Product Id:" . $prods["prodid"] . " ––> " . "Categories Id:" . $prods["catid"];
}
} else {
echo "0 results";
}
$q2 =
" SELECT `ID`.`category` as `IDName`, `LABEL`.`category` as `LabelName`, `LABEL`.`catid` as `LabelId`
FROM `categories` as ID
INNER JOIN `categories` as LABEL
ON `ID`.`catid` = `LABEL`.`parentid`";
$result2 = $conn->query($q2);
if ($result2->num_rows > 0) {
while($prods = $result2->fetch_assoc()) {
echo "ID# " . $prods["LabelId"] . " is called: ". $prods["LabelName"] . "<br>";
}
} else {
echo "0 results";
}
$conn->close();
I have tried adding another INNER JOIN with no luck in the results.
The end result I am after would be: PROD ID #0 belongs to Sneakers, Nike, Jordan.
Anyone can point me in the right direction?
Thank you so much,
Sergio
UPDATE - 10/11/16
The Query:
$q =
" SELECT PC.productid as productid, concat_WS('~',C1.category, C2.category, C3.category) as breadcrumb
FROM xcart_categories as C1
INNER JOIN xcart_products_categories as PC
ON C1.categoryid = PC.categoryid
LEFT JOIN xcart_categories as C2
ON C1.categoryid = C2.parentid
AND C1.parentid = 0
LEFT JOIN xcart_categories as C3
ON C2.categoryid = C3.parentid
WHERE C1.parentid = 0
";
The Fetch:
$result = $conn->query($q);
if ($result->num_rows > 0) {
while($prods = $result->fetch_assoc()) {
echo $prods['productid'] . ' Belongs in these categories: ' . $prods['breadcrumb'] . '<br>';
}
} else {
echo "0 results";
}
This assumes 3 levels of hierarchy no more and a separate join is needed to "put each record on the same line" so they can be combined into a single value result. I thin you were trying to use Group_concat but I can't see how that's going to work as you don't have a way to walk the hierarchy.
SELECT PC.ProductID, concat_WS('-',C1.Category, C2.Category, C3.Category) as breadcrumb
FROM categories C1
INNER JOIN ProductsCategories PC
on C1.categoryID = PC.CategoryID
LEFT JOIN categories C2
on c1.CategoryID = C2.ParentID
and C1.parentID = 0
LEFT Join Categories C3
on C2.CategoryID = C3.ParentID
WHERE C1.ParentID = 0
Working SQL Fiddle example ( this only supports 3 levels deep, but could be altered with added left joins to support a max level but not a undetermined max level..)
I see you're trying to use group concat to bring all the rows for the same product category.productID of 0 to the same line
However as 0 references catID of 1 it would only return "sneakers" on the inner join. You would need to traverse the tree (all of it) somehow, thus the above, or you have to take multiple trips to the db or use some sort of dynamic SQL or method mentioned in link in comments.
This would be fairly simple in SQL Server, Oracle or other Enterprise RDBMS systems, however without recursive queries or engine specific hierarchy queries, this is no easy feat in MySQL on a single trip.
Maybe I'm missing something so it may help to see the actual expected results for your sample data. What is the record set look like that you want back?
I have 2 tables that I want to merge. I want to print all the products with their corresponding total quantity and total amount.
This is what I have.
//Product Table
productID productName
1 A
2 B
3 C
//Order Record (This came from 2 tables that I have successfully merged)
orderID productID quantity amount
1 1 5 100
2 2 2 50
3 2 3 150
I want to do this
productID productName totalQuantity totalAmount
1 A 8 250
2 B 2 50
3 C 0 0
//instead of 0 for total Quantity and total Amount, it shows 2 and 50 respectively.
Here is my php code. It correctly outputs the the data for the first 2 rows (product A and B) but when it comes to the last row (product C), it copies the data for product B. Please tell me what's wrong in my code? Thank you in advance.
$products = $wpdb->get_results("SELECT * FROM wp_products");
foreach($products as $product){
$productID = $product->productID;
$productName = $product->productName;
$orders = $wpdb->get_results("SELECT a.productID, SUM(a.quantity) as totalQuantity, SUM(a.amount) as totalSales FROM a INNER JOIN b ON a.orderID = b.orderID GROUP BY productID");
if(is_null($orders)){
$totalQuantity = 0;
$totalSales = '0.00';
}
foreach($orders as $order){
$totalQuantity = $order->totalQuantity;
$totalSales = $order->totalSales;
}
$orderItem = array(
'productID' => $productID,
'productName' => $productName,
'totalQuantity' => $totalQuantity,
'totalSales' => $totalSales
);
$records[] = $orderItem;
}
Quick fix is (just add WHERE to your query):
$orders = $wpdb->get_results("SELECT
a.productID,
SUM(a.quantity) as totalQuantity,
SUM(a.amount) as totalSales
FROM a
INNER JOIN b
ON a.orderID = b.orderID
WHERE a.productID = $productID
GROUP BY productID");
But looking at your fragment, I believe you can simplify it (replace full fragment) to:
$records = $wpdb->get_results("SELECT
p.productID,
p.productName,
COALESCE(SUM(a.quantity),0) as totalQuantity,
COALESCE(SUM(a.amount),0) as totalSales
FROM wp_products p
LEFT JOIN a
GROUP BY p.productID");
I don't believe your query is correct.
I don't see the table names. Try changing it to:
FROM `tablename` AS a INNER JOIN `othertable` AS b
Swap out tablename and other table with the names for table a and b.
I have a table name products with all product details and another whs_products with quantity details of the products for each warehouse.
i want select id, code and name from products table and sum of quantity where products.id = whs_products.product_id
I am trying this
$this->db->select("id, code, name");
$this->db->from("products");
$this->db->join('whs_products', 'products.id = whs_products.product_id');
$this->db->select("quantity");
I getting the list products that exists in whs_products not the sum. Some products are listed twice as they have 2 entries in whs_products.
I want list all the products once only where no quantity I want put 0 in quantity and where its is more than 1 in whs_products I want display sum of all the quantity
Help will be much appreciated!
Table Structure
Products
id, code, name, unit, price
whs_products
id, product_id, warehouse_id, quantity
I have whs table too for warehouse
id, name, address
I tried this Sir,
$this->db->select("products.id as productid, products.code, products.name, products.unit, products.cost, products.price, sum(whs_products.quantity) as 'totalQuantity'")
->from('products')
->join('whs_products', 'whs_products.product_id=products.id', 'left')
->group_by("products.id");
$this->db->get();
Every thing is fine. But the total number of products are calculated wrongly. I think system add 1 to total products, each time gets quantity from whs_products. For some products quantity is 2 or 3 time depending on each warehouse.
Any solutions for this. I am very thankful for your support.
Please try out the following query and comment.
SQLFIDDLE DEMO
Sample data:-
Products
PID PNAME
1 j
2 k
3 m
whs_Products
WID PID QUANTITY
11 2 300
11 2 200
14 2 500
11 1 300
15 3 100
14 3 800
Query to get total by pid in whs_products
select pid, wid, sum(quantity)
from whs_products
group by pid, wid
;
Results:
PID WID SUM(QUANTITY)
1 11 300
2 11 500
2 14 500
3 14 800
3 15 100
query using a variable to get user input for pid and by pid, wid
-- group by pid and wid
set #var:='2'
;
select a.pid, b.pname, a.wid, sum(a.quantity)
from whs_products a
join products b
on b.pid = a.pid
where a.pid = #var
group by a.pid, wid
;
Results:
PID PNAME WID SUM(A.QUANTITY)
2 k 11 500
2 k 14 500
final query to show quantity by user input pid only
Query:
-- by pid only
set #var:='2'
;
select a.pid, b.pname, sum(a.quantity)
from whs_products a
join products b
on b.pid = a.pid
where a.pid = #var
group by a.pid
;
Results:
PID PNAME SUM(A.QUANTITY)
2 k 1000
Since OP wants in CodeIgniter
Here is a headstart for you to try. At first I had the impression you already know the syntax of codeigniter and you are looking for SQL logic, so you could convert it into the desired format you need.
$this->db->select("a.pid, b.pname, count(a.quantity) as 'toalQuantity'");
$this->db->from('wsh_products a');
$this->db->join('products b', 'a.pid=b.pid', 'inner');
$this->db->group_by("a.pid");
$where = "a.pid = 2";
$this->db->get();
$query->results_array();
Or write a funciton :) :
function getQuantity($prodid = false)
{
$this->db->select(a.pid, b.pname, count(a.quantity) as 'toalQuantity');
$this->db->join('wsh_products a', 'a.pid=b.pid');
if ($prodid !== false)
$this->db->where('a.pid', $prodid);
$query = $this->db->get('products b');
if($query->result() == TRUE)
{
foreach($query->result_array() as $row)
{
$result[] = $row;
}
return $result;
}
}
Edit as OP requested for LEFT JOIN in comments
SQLFIDDLE
To show all products in Products table, do the following:
In select show pid from Products table.
Use from Products Left Join Whs_Products
Group by pid from Products table
I have set the PHP variable $accountnumber to be that of the user who is viewing their profile page. On the page, I have a block with the user's information populated from the database, and I have a list of all products that we have, and I want to put a check mark next to each one that the customer has by assigning a class to it.
Here are my tables:
products
id | name | url | weight
100 p1 p1.html 1
101 p2 p2.html 2
102 p3 p3.html 3
103 p4 p4.html 4
104 p5 p5.html 5
105 p6 p6.html 6
products_accounts
account_number | product_id
0000001 100
0000001 104
0000001 105
0000002 101
0000002 103
0000002 104
0000002 105
0000003 100
0000003 102
I tried a LEFT OUTER JOIN, but was not able to determine if the $accountnumber matched an account_number in the products_accounts table for a specific product_id. The only way that I was able to accomplish this was to add a WHERE statement like this:
WHERE products_acccounts.account_number = '$accountnumber'
It gave the proper class to the product, but only showed the product that they had instead of all.
Here's my code:
$sql ="
SELECT
products.id,
products.name,
products.url,
products_accounts.account_number
FROM
products
LEFT OUTER JOIN
products_accounts
ON
products.id = products_accounts.product_id
";
$sql .="
GROUP BY
products.id
ORDER BY
products.weight
";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result)) {
echo '<span class="'; if($row['account_number'] == '$accountnumber')
{ echo'product_yes">'; } else { echo 'product_no">'; }
echo '' . $row['name'] . '<br /></span>';
}
If a customer has all product except P2 and P5, it SHOULD display like this:
✓P1
P2
✓P3
✓P4
P5
✓P6
It's better to filter out rows using SQL than PHP, like below:
$sql ="
SELECT
p.id,
p.name,
p.url,
pa.account_number
FROM
products p
LEFT OUTER JOIN
products_accounts pa
ON
p.id = pa.product_id
AND
pa.account_number = ".mysql_real_escape_string($accountnumber)."
ORDER BY
p.weight
";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result)) {
echo '<span class="'; if(!is_null($row['account_number']))
{ echo'product_yes">'; } else { echo 'product_no">'; }
echo '' . $row['name'] . '<br /></span>';
}
$getproducts = mysql_query("
SELECT id, name, url
FROM products
ORDER BY weight ASC");
while ($rowproducts = mysql_fetch_assoc($getproducts)) {
$product_id = $rowproduct['id'];
$product_name = $rowproduct['name'];
$product_url = $rowproduct['url'];
$getuserhasproduct = mysql_query("
SELECT DISTINCT product_id
FROM products_accounts
WHERE account_number = $accountnumber
AND product_id = $product_id");
$user_has_product = mysql_num_rows($getuserhasproduct);
if($user_has_product){
$class = "checked";
}
echo "<span class='$class'><a href='$product_url'>$product_name</a></span>";
unset($class);
} // end loop
This might help with performance
$getproducts = mysql_query("SELECT id, name, url,
(SELECT DISTINCT product_id
FROM products_accounts
WHERE account_number = '$accountnumber'
AND product_id = products.id) AS product_count
FROM products
ORDER BY weight ASC");
while ($rowproducts = mysql_fetch_assoc($getproducts)) {
$product_id = $rowproduct['id'];
$product_name = $rowproduct['name'];
$product_url = $rowproduct['url'];
$product_count = $rowproduct['product_count'];
if($product_count > 0){
$class = "checked";
}
echo "<span class='$class'><a href='$product_url'>$product_name</a></span>";
unset($class);
} // end loop
SELECT
products.id,
products.name,
products.url,
products_accounts.account_number
FROM
products
LEFT OUTER JOIN
(SELECT * FROM products_accounts WHERE account_number = $account_number) as products
ON
products.id = products_accounts.product_id
WHERE
";
$sql .="
GROUP BY
products.id
ORDER BY
products.weight
";
i think this is your answer, you need to filter your join table before the join. please check the syntax as i am not that familiar with php.
You're trying to use GROUP BY in a context that doesn't make sense if you want to retrieve all of the records. The GROUP BY clause should only be used if you want to aggregate data (i.e. get the sum, average, etc. of a bunch of records).