How could/should I write this SQL query? - php

I need to write an SQL query to list a customers prices for our products. We have a standard price list, customer_no = 0, and a customer specific price list, customer_no = XXXX.
I am having trouble understanding how I can get the query to return the customer specific price for a product, if they've been given such, or if not fall back to the standard price.
To get all products and prices on the standard price list
select prices.product_id, products.product_desc, prices.m2
from prices, products
where prices.product_id = products.product_id
and prices.customer_no = 0
order by prices.product_id asc
To get all products and prices that the customer has been specifically quoted for
select prices.product_id, products.product_desc, prices.m2
from prices, products
where prices.product_id = products.product_id
and prices.customer_no = $_SESSION['customer']
order by prices.product_id asc
How can I perform the first query, but if the customer has their own price then replace it with that? Is this even possible?
Thanks in advance.
Steve
Edit: Sorry, missed the third line in both queries in the original post.

You have to join with the prices table twice, once for the list prices and then for the quoted prices. Use a LEFT JOIN for the latter, since some products won't have a quoted price. Then use NVL to default from the quoted price to the list price.
SELECT products.product_id, products.product_desc, NVL(p2.m2, p1.m2)
FROM products
JOIN prices p1 ON p1.product_id = products.product_id
LEFT JOIN prices p2 ON p2.product_id = products.product_id
AND p2.customer_no = $_SESSION['customer']
WHERE p1.customer_no = 0

Try:
select prices.product_id, products.product_desc, prices.m2
from prices, products
where prices.customer_no = nvl($_SESSION['customer'], 0)
order by prices.product_id asc

Related

My query is slow when ever I select inside concat or group_concat and I want to return them in form of JSON. how can I make it faster?

I have a discount table (productdiscounts) where I inserted product ID and the accounts that I wish to give discount. e.g all users under ABC account should be given a discount of 10% and users under account XZS should be given a discount of 90%, etc.
secondly I selected all the available accounts and the discounts associated to them as alldiscounts for staff to see which accounts have discount on a product.
SELECT
products.manufacturer as manufacturerID, stock.expiryDate,
*coalesce((select discount from productdiscounts where(productID=products.id and branchID=? and isActive='1' and patients.billingAccounts like concat('%\"',productdiscounts.accountID,'\"%')) order by discount desc limit 1),0.00) as discount*,
**concat('[',(select
group_concat('{\"productID\":\"',productdiscounts.productID,'\",\"accountID\":\"',productdiscounts.accountID,'\",\"discount\":\"',productdiscounts.discount,'\",\"accountName\":\"',accounts.name,'\",\"accountNo\":\"',accounts.accountNo,'\"}') from productdiscounts
left join accounts on(productdiscounts.accountID=accounts.id)
where(productdiscounts.productID=products.id and productdiscounts.branchID = ? and productdiscounts.isActive = '1' )),']') as allDiscounts**
from products
This is a sample patient record
enter image description here
This is how i store each product with accounts that
enter image description here
A patient can have more than one account which 99% of them do, and that's why I couldn't use "accounID = ". E.g A patient maybe associated with his corporate account which doesn't cover all the services and has to use his private account to pay for those services not covered under his/her corporate account.
I associated corporate accounts and their discount on each product so that I can check the patient's billing accounts while searching a product and if the product is covered under any or all the patient's billing account, then return the discount, otherwise return 0.00.
Because it's the same query for searching a product and listing all the products. In this section, I'm returning all the discounts associated to a product in order to guide staff on the status of the product.
concat('[',(select group_concat('{\"productID\":\"',productdiscounts.productID,'\",\"accountID\":\"',productdiscounts.accountID,'\",\"discount\":\"',productdiscounts.discount,'\",\"accountName\":\"',accounts.name,'\",\"accountNo\":\"',accounts.accountNo,'\"}') from productdiscounts
left join accounts on(productdiscounts.accountID=accounts.id)
where(productdiscounts.productID=products.id and productdiscounts.branchID = ? and productdiscounts.isActive = '1' )),']') as allDiscounts
FULL CODE FOR REVIEW
$searchSQL="select
distinct products.id,
products.type as productType,
products.brand,
products.status,
products.productCode,
products.generics,
stock.stockID,
stock.stockIn,
stock.description,
stock.quantity as stockQty,
pricetags.costPrice,
pricetags.sellingPrice,
pricetags.percentageMarkup,
countries.country as manufacturer,
products.manufacturer as manufacturerID,
stock.expiryDate,
coalesce((select discount from productdiscounts where(productID=products.id and branchID=? and isActive='1' and patients.billingAccounts like concat('%\"',productdiscounts.accountID,'\"%')) order by discount desc limit 1),0.00) as discount,
concat('[',(select group_concat('{\"productID\":\"',productdiscounts.productID,'\",\"accountID\":\"',productdiscounts.accountID,'\",\"discount\":\"',productdiscounts.discount,'\",\"accountName\":\"',accounts.name,'\",\"accountNo\":\"',accounts.accountNo,'\"}') from productdiscounts
left join accounts on(productdiscounts.accountID=accounts.id)
where(productdiscounts.productID=products.id and productdiscounts.branchID = ? and productdiscounts.isActive = '1' )),']') as allDiscounts
from products
left join stock on (products.id=stock.productID)
left join pricetags on (stock.priceTag=pricetags.id)
left join countries on (products.manufacturer=countries.id)
left join diagnosis on (diagnosis.diagnosisRef=?)
left join patients on (patients.patientNo=diagnosis.patientNo)
where(
(
products.productCode=? or
products.generics like concat('%\"',?,'%\"%') or
(";
foreach($needleArray as $needle){
$searchSQL.="(products.brand like concat(?,'%') or products.brand like concat('% ',?,'%')) and ";
$productsQParams[]=$needle;
$productsQParams[]=$needle;
}
$searchSQL=rtrim($searchSQL," and ");
$searchSQL.="
)
) and (";
if($chkStockQty === "True"){
$searchSQL.=" `stock`.`quantity` > 0 and ";
}
$searchSQL.=" stock.branchID={$branchID} and
stock.isActive='1' and
products.status='active'
)
) order by products.brand limit $offset,$rowCount";
SEE FINAL OUTPUT HERE
enter image description here
This is the query. I hope is what you are asking for. Thank You
select
distinct products.id,
products.type as productType,
products.brand,
products.status,
products.productCode,
products.generics,
stock.stockID,
stock.stockIn,
stock.description,
stock.quantity as stockQty,
pricetags.costPrice,
pricetags.sellingPrice,
pricetags.percentageMarkup,
countries.country as manufacturer,
products.manufacturer as manufacturerID,
stock.expiryDate,
coalesce((select discount from productdiscounts where(productID=products.id and branchID=1 and isActive='1' and patients.billingAccounts like concat('%\"',productdiscounts.accountID,'\"%')) order by discount desc limit 1),0.00) as discount,
concat('[',(select group_concat('{\"productID\":\"',productdiscounts.productID,'\",\"accountID\":\"',productdiscounts.accountID,'\",\"discount\":\"',productdiscounts.discount,'\",\"accountName\":\"',accounts.name,'\",\"accountNo\":\"',accounts.accountNo,'\"}') from productdiscounts
left join accounts on(productdiscounts.accountID=accounts.id)
where(productdiscounts.productID=products.id and productdiscounts.branchID = 1 and productdiscounts.isActive = '1' )),']') as allDiscounts
from products
left join stock on (products.id=stock.productID)
left join pricetags on (stock.priceTag=pricetags.id)
left join countries on (products.manufacturer=countries.id)
left join diagnosis on (diagnosis.diagnosisRef='')
left join patients on (patients.patientNo=diagnosis.patientNo)
where(
(
products.generics like concat('%pan%')
) and ( stock.branchID=1 and
stock.isActive='1' and
products.status='active'
)
)
and patients.billingAccounts like concat('%\"',productdiscounts.accountID,
'\"%')
Is that fishing around in a JSON string? Can't you supply the whole accountID so you don't have to do the slow LIKE with a leading wild card?
With = instead of LIKE, this might help the first subquery:
INDEX(branchID, isActive, productID, AccountID, discount)
It might be more practical to do
SELECT COALESCE(MAX(discount), 0) ...
instead of the ORDER BY discount DESC LIMIT 1.
The other parts may benefit from
patients: INDEX(billingAccounts)
productdiscounts: INDEX(accountID)
Please provide SHOW CREATE TABLE and EXPLAIN SELECT ...

Update Subtract qty - SQL

I have the following DB structure
Table product (which holds my products information including the stock)
prod_id
prod_name
prod_desc
prod_price
stock
table store_orders_item (which is updated every time a customer buys from the my site)
id
order_id
sel_prod_id
sel_prod_price
sel_prod_qty
I need that every time I make a sale online and store_orders_items is updates, that reduce the stock field of the product sold on the table product
I think i need to use the code below, plus some sort of join or subquery to update my product table according to the prod_id, but i could not figure out how.
UPDATE product SET stock = stock - (SELECT SUM(sel_prod_qty) FROM store_orders_items);
I also tried:
UPDATE product
SET stock = stock - (SELECT s.sel_prod_qty, s.sel_prod_id, p.prod_id
FROM store_orders_items as s left join product as p ON
s.sel_prod_id=p.prod_id WHERE order_id=(SELECT MAX(order_id) from orders_number));
And got this error:
"You can't specify target table 'product' for update in FROM clause"
You must use join updates, for example in MySQL:
UPDATE
product p
INNER JOIN
store_orders_item s
ON
p.prod_id = s.sel_prod_id
SET
p.stock = p.stock - s.sel_prod_qty
WHERE
s.order_id = NNNNN
where NNNNN is the id of order just inserted.

Display featured products on top of display

I am working on opencart and fetching a list of products using below mentioned query and these products are displayed with most recent product on top.
$result = mysqli_query($con,"select p.image,p.price,p.store_name,p.deal_title_url,p.shop_now_url,p.coupon_code,p.special_deal_txt,p.special_comment_txt,s.price,d.name,p.date_added from oc_product p, oc_product_special s,oc_product_description d where p.product_id=s.product_id and p.product_id=d.product_id order by p.date_added DESC $limit;");
Note -
1. Limit is for pagenation
2. Data is fetched from multiple tables
Now i want to display all the featured products on top of the display. So basically the products which are in featured array must always be displayed on top and then remaining products based on the creation date.
The featured product id's are kept in an array - $featured_array
How can this be done?
Note that number of featured products may vary.
Try using UNION. In first query get featured products, in second put your current query. Limit is for union result
(
select p.image,p.price,p.store_name,p.deal_title_url,p.shop_now_url,p.coupon_code,p.special_deal_txt,p.special_comment_txt,s.price,d.name,p.date_added from oc_product p, oc_product_special s,oc_product_description d where p.product_id=s.product_id and p.product_id=d.product_id AND p.product_id IN($featuredProductsIds) order by p.date_added DESC
)
UNION
(
select p.image,p.price,p.store_name,p.deal_title_url,p.shop_now_url,p.coupon_code,p.special_deal_txt,p.special_comment_txt,s.price,d.name,p.date_added from oc_product p, oc_product_special s,oc_product_description d where p.product_id=s.product_id and p.product_id=d.product_id order by p.date_added DESC
)
$limit;

How should i order by price in this case

I want to order by price. But I am getting the price from two different table and compare it to get the minimum price and print it if price is above 0. It is also possible that price is present in only one database. The rough structure of my code is:
query1 = choose products
while = fetch the products details {
query2 = get the price1, order by price1
query3 = get the price2, order by price2
if statement to get the minimum price so price = minimum price
if (price>0) {
echo product result
}
}
How can I order the result according to the price?
EDIT: Product is already selected, i want to acquire the price of products from two different price table
You can do it in just one query, much more efficiently:
SELECT `a`.*, LEAST(`b`.`price`,`c`.`price`) AS `price`
FROM `products` `a`
JOIN `price1` `b` ON `a`.`id`=`b`.`product_id`
JOIN `price2` `c` on `a`.`id`=`c`.`product_id`
WHERE `price`>0
ORDER BY `price` ASC
Adjust according to your database's tables and columns.

Magento: find orders containing a product

Is there a way in Magento to find all orders that contain a given product? It would be even better if it could be done from the administration panel.
Reports -> Products -> Products Ordered gives me the day the product was sold and how many orders contain it, but I need to know which specific orders include the product.
Thank you!
I answered this question in another question;
Get a list of orders in magento extension that have a certain product
For quick reference:
$productId = {PRODUCT_ID};
$orders = array();
$collection = Mage::getResourceModel('sales/order_item_collection')
->addAttributeToFilter('product_id', array('eq' => $productId))
->load();
foreach($collection as $orderItem) {
$orders[$orderItem->getOrder()->getIncrementId()] = $orderItem->getOrder();
}
You can get by simple mysql query:-
select order_id from sales_flat_order_item where product_id=//given product id
OR
You can customize the reports according to your needs.
If you want to get the increment_id (the incremental Order Number) instead of the order_id, you can simply use this Statement:
SELECT o.increment_id
FROM sales_flat_order_item oi
INNER JOIN sales_flat_order o ON o.entity_id = oi.order_id
WHERE product_id=XXX ORDER BY o.increment_id DESC;

Categories