Separate a mysql array into a query - php

I've a problem with MySQL query. I'm trying select products info over the order products list, but it are selecting only the first record, being that the products list is a array.
Example: being orders.itens = "10,11,12,13", the "IN" selects only the first ID, "10". How I do to select all ID's, something that sounds like implode function in PHP?
SELECT
orders.id,
products.name,
products.price
FROM
orders,
products
WHERE
products.id IN (orders.itens)
Thank you

You want to do a join:
SELECT o.id, p.name, p.price
FROM orders o join
products p
on find_in_set(p.id, o.items) > 0;
Unfortunately, there is no way to optimize this query. You should created an association/junction table, probably called OrderProducts that contains one row for each product in an order.

I guess you need something like this
select CONCAT('"',CONCAT(Replace("10,11,12,13", ',', '","'),'"')) as str
And use this as the value for in clause

Related

2 INNER JOIN For 2 colums that use the same foreign key

First, I have my database like this:
And the relations:
And now in the .php I want to create the table that shows everything in the table but instead of showing ProductId and UpgradeProductId as a number, I want to show them as name of the product
The problem is how can I do it? I already made this
And it show up like this
I want the [UpgradeProductId] to come out as Product Name like [ProductId] but I don't know how to write it to connect the SQL and have a result.
I hope I understood your question correctly.
The easy way to display the ProductName for your UpgradeProductId would be a SELECT statement for the column.
The statement would look like that:
SELECT UpgradeId, Productname, (SELECT Product.ProductName FROM Product WHERE Product.ProductId = Upgrade.UpgradeProductId), UpgradeDate, UpgradeDetail
FROM Upgrade
INNER JOIN Product ON Upgrade.ProductId = Product.ProductId
INNER JOIN RepairMan ON Upgrade.RepairManId = RepairMan.RepairManId
WHERE Upgrade.RepairManId = '$RepairManId'
ORDER BY UpgradeId ASC
However I guess, that this is not the most efficient solution.
To do the same with joins, you have to use aliases for your joined tables. It would look like this:
SELECT UpgradeId, P1.Productname, P2.Productname, UpgradeDate, UpgradeDetail
FROM Upgrade
INNER JOIN Product AS P1 ON Upgrade.ProductId = P1.ProductId
INNER JOIN Product AS P2 ON Upgrade.UpgradeProductId = P2.ProductId
INNER JOIN RepairMan ON Upgrade.RepairManId = RepairMan.RepairManId
WHERE Upgrade.RepairManId = '$RepairManId'
ORDER BY UpgradeId ASC
Another thing besides that. I don't know exactly which SQL you are using, but be sure to add either ASC or DESC to your ORDER command. Without this addition, some types of SQL tend to not order as you intended.

Using multiple inner joins

I have four tables:
users, orders, orders_product and products.
They are connected to each other by foreign key
user tables contains: id, name, email and username.
product table contains: id, product_name, product_description and product_price
orders table contains: id, u_id(foreign key).
orders_product table contains: id, product_id(foreign key), order_id(foreign key).
Now I was trying to fetch the name of a user with the total price of a particular order that he has placed.
The maximum I could went for was something like this:
SELECT prod.order_id,
SUM(product_price) AS Total
FROM products
INNER JOIN
(SELECT orders.id AS order_id,
orders_product.product_id
FROM orders
INNER JOIN orders_product ON orders.id = orders_product.order_id
WHERE order_id=1) AS prod ON products.id = prod.product_id;
It showed me total price of a particular order. Now I have two questions:
Is that query correct. It looks like a very long query. Can the same result be achieved with a smaller one?
How to fetch the name of a user with the total price of a particular order that he has placed.
Hi some addition to #Gordon Linoff
your query seems ok.
if you store your price data in order_products it will be good and some benefit, one of these benefit is aggregation will be simple. Second benefit if product price change it will not affect to order.
Your query is correct for one order, but it can be improved:
Don't use a subquery unless necessary. In MySQL this introduces additional overhead.
You are only looking at one order, which seems on the light site. You should remove the where clause.
You should be using a group by because you want aggregation.
You need to join in the user table to get the name.
I also added table aliases (abbreviations for table names). This makes the query a bit more readable:
SELECT u.name, SUM(p.product_price) as Total
FROM orders_product op INNER JOIN
orders o
ON o.id = op.order_id INNER JOIN
products p
ON p.id = op.product_id INNER JOIN
users u
on o.userid = u.id
WHERE op.order_id = 1
GROUP BY u.name;
Your SQL is wrong. Because You want to calculate specific to user. But your SQL is specific to Order. Your SQL will give result for One Order. Please make it User Specific by giving user name or what ever is unique.

Mysqli Select statement to count total orders and display all ordered products

With the select statement below I'm getting a nice view of all my orders. But what I'm trying to achieve is to get all the totals and the individual ordered products in one select statement. Maybe the ordered products can be placed in an Array? If this is possible, I also would like to know the way to print these individual products.
Can anyone please advise?
Thanks in advance.
SELECT statement:
SELECT order.order_id, DATE_FORMAT(order.date_added,'%Y/%m/%d - %H:%i'),
COUNT(order_product.order_id),
SUM(order_product.quantity),
SUM(order_product.cost)
FROM order
LEFT JOIN order_product ON order.order_id = order_product.order_id
GROUP BY order_product.order_id ORDER BY date_added DESC
GROUP_CONCAT is probably the most suitable thing here. It will concatenate multiple values into one string column. For example:
SELECT order.order_id, DATE_FORMAT(order.date_added,'%Y/%m/%d - %H:%i'),
GROUP_CONCAT(order_product.name SEPARATOR ', ') AS Products,
COUNT(order_product.order_id) AS NumberOfLines,
SUM(order_product.quantity) AS TotalQuantity,
SUM(order_product.cost) AS TotalCost
FROM order
LEFT JOIN order_product USING(order_id)
GROUP BY order_product.order_id
ORDER BY date_added DESC
You could alternatively use a separator of a single comma (that's the default), and then use explode(',', $products) in PHP to get an array of the product names.

Query Between two date

SELECT product.pname,stock.pid,stock.qty,stock.rate
FROM product,stock
WHERE (date BETWEEN '2012-04-10' AND '2012-07-16') AND product.pid=stock.pid
This is my sql query but problem is when execute this query its show single result means my product table contains pid and pname and stock table contains pid,rate,qty and date.
I want to display record between two dates.
My query match with two records. But when i add "AND product.pid=stock.pid" its show only 1 record.
I want to display the product name from product table in the respect of pid of stock table.
Probably some product is not in the stock. Also I recommend you to do a JOIN like this:
SELECT product.pname,stock.pid,stock.qty,stock.rate
FROM product
LEFT JOIN
stock
ON product.pid=stock.pid
WHERE (date BETWEEN '2012-04-10' AND '2012-07-16')
I used LEFT JOIN that means to return products no matter if have or nor stock, I think that with this query you will get two Rows.
First try to get it working without the join:
SELECT stock.pid, stock.qty, stock.rate
FROM stock
WHERE stock.date BETWEEN '2012-04-10' AND '2012-07-16'
If that works, then use an outer to join to add information to each row without removing any rows.
SELECT product.pname, stock.pid, stock.qty, stock.rate
FROM stock
LEFT JOIN product ON product.pid=stock.pid
WHERE stock.date BETWEEN '2012-04-10' AND '2012-07-16'
The product name will be NULL if no product is found.
Try the below query.
SELECT product.pname,stock.pid,stock.qty,stock.rate
FROM product,stock
WHERE stock.date BETWEEN '2012-04-10' AND '2012-07-16' AND product.pid=stock.pid
Your selection criteria
WHERE ([stock.]date BETWEEN '2012-04-10' AND '2012-07-16')
makes it effectively RIGHT JOIN, only records that have/had stock within date range will be displayed. If you want to display ALL products irrespective of stock than you will need to add OR [stock.]date IS NULL to your selection criteria.

SQL Select multiple matching rows

I have a SQL database of products from different suppliers, so the same product could appear multiple times with different prices.
Is it possible to select all of the products that have more than 4 prices, so bascially all of the rows which have more than 4 rows with the same ID?
You could add COUNT(*) AS number_of_products to SELECT, GROUP BY product_id, then use HAVING number_of_products > 4.
Note that HAVING is applied on the results (it basically goes through all the results, one by one, and applies the conditions), so it will be slower than WHERE. If you have hundreds of thousands of rows and you need performance, consider pre-counting the products, storing the indexed count value somewhere, then using a simple WHERE instead.
Yes, GROUP on the identificator for your item, and specify the number of prices to count in a HAVING clause, something like this :
SELECT ItemID, COUNT(Price) FROM itemTBL GROUP BY ItemID HAVING COUNT(Price) >= 4
You can then use this to later filter and get more information:
SELECT Item.*, Category.Name, Filter.NumPrices from itemTBL AS Item
INNER JOIN categoryTBL as Category ON Item.CategoryID = Category.CategoryID
INNER JOIN (SELECT ItemID, COUNT(Price) AS NumPrices FROM itemTBL GROUP BY ItemID HAVING COUNT(Price) >= 4) AS Filter on Item.ItemID = Filter.ItemID
This is the perfect thing for a group by:
SELECT ProductID, COUNT(*) AS PriceCount
FROM Product GROUP BY
Product,Price HAVING COUNT(Product) > 4

Categories