Select between range of values in 2 tables - mysql

I have 2 tables
-- Purchases --
Id | IdProvider | Date | Observations
and
-- PurchasesDetails --
Id | IdProduct | Quantity | Price
where Purchases.Id = PurchasesDetails.Id
I want to make a SQL query where it returns all the purchases between a range of price (The price info is on PurchasesDetails table -> Quantity*Price)
For example: Get all the purchases that costed more than 0$ but less than 500$
I've tried this:
SELECT * FROM Purchases INNER JOIN PurchasesDetails ON Purchases.Id = PurchasesDetails.Id WHERE Purchases .Id sum(PurchasesDetails.Price*PurchasesDetails.Quantity) BETWEEN 0 AND 500
But it doesn't work. Seems like I'm missing a condition to link up all the PurchasesDetails with the same Id
I think it's a really easy task but I'm stuck there for few hours so all the help are welcome!!

Is this what you want?
SELECT p.*,
SUM(pd.Price * pd.Quantity) as purchase_total
FROM Purchases p INNER JOIN
PurchasesDetails pd
ON p.Id = pd.Id
GROUP BY p.Id
HAVING purchase_total BETWEEN 0 AND 500;
Note that SELECT p.* is fine with GROUP BY p.id, assuming that id is unique in Purchases.

Related

SQL Select data and if loop

I must SELECT and JOIN data from tables. For example I have table:
PRODUCTS: id | productName
PRICES: id | idProduct | price1
PRICES_GROUPS: id | idProduct | price2
When idProducts exist on table PRICES_GROUPS I must get "price2" when not exist I must get "price1" from tabel PRICES
I use mySQL. Any idea to solution this problem?
In you case you can try
select p.*,COALESCE(pg.price2,pc.price1) as price from PRODUCTS p left join PRICES_GROUPS pg on pg.idProduct = p.id left join PRICES pc on pc.idProduct = p.id;

Select from multiple tables even if one doesn't have any corresponding record

I have three tables: product, sale and purchase.
I need to get the sum of sales and the sum of purchases of the products.
Even if no sales were made, I need it to show the purchases and vice-versa.
Something like:
Product | Sum of sales | Sum of purchases |
____________________________________________
product 1 | 10000 | 45000 |
product 2 | 20000 | 0 (or null) |
product 3 | 0(or null) | 20000 |
I've tried this, but it'll only return products that have both sales and purchases simultaneously:
select prod.name, sum(s.total), sum(p.total)
from product prod
inner join sale s on s.prod_id = prod.id
inner join purchase p on p.prod_id = prod.id
group by 1;
Thanks in advance.
Your query has a couple of issues. Firstly, because of the INNER JOIN it will (as you found) only return values for products which have both sales and purchases. This can be resolved by using LEFT JOIN (with an optional COALESCE to convert null values into 0). The second problem is that you will get duplicate rows from your JOIN where there is more than one sale or purchase of a product. To work around that, you need to perform the aggregation in derived tables for sales and purchases:
SELECT pr.name,
s.total AS sales, -- will show null if no sales
COALESCE(p.total, 0) AS purchases -- will show 0 if no purchases
FROM product pr
LEFT JOIN (SELECT prod_id, SUM(total) AS total
FROM sale
GROUP BY prod_id) s ON s.prod_id = pr.id
LEFT JOIN (SELECT prod_id, SUM(total) AS total
FROM purchase
GROUP BY prod_id) p ON p.prod_id = pr.id

SQL query to get results between 2 tables, and the second one has 3 possibilities of returning data

Even though my question was warned as similar title, I couldn't find here any similar problem. Let me explain in details:
I've got two tables (I'm working with MySQL) with these values inserted:
table products:
id name
1 TV
2 RADIO
3 COMPUTER
table sales (product_id is A FK which references products(id)):
id quantity product_id
1 50 2
2 100 3
3 200 3
The tv's haven't been sold, radios got 1 sale (of 50 unities) and computers got two sales (one of 100 e other of 200 unities);
Now I must create a query where I can show the products and its sales, but there are some conditions that make that task difficult:
1 - If there's no sales, show obviously NULL;
2 - If there's 1 sale, show that sale;
3 - If there's more than 1 sale, show the latest sale (which I've tried to use function MAX(id) to make it simple, and yet didn't worked);
In the tables example above, I expect to show this, after a proper SQL Query:
products.NAME sales.QUANTITY
TV NULL
RADIO 50
COMPUTER 200
I've been trying lots of joins, inner joins, etc., but couldn't find the result I expect. Which SQL query can give the answer I expect?
Any help will be very appreciated.
Thanks.
Hope the below query works.
SELECT products.name, sl.quantity
FROM products LEFT JOIN (
SELECT product_id, max(quantity) as quantity FROM sales GROUP BY product_id) sl
ON products.id = sl.product_id
In MySQL 8.0 you can do:
with m (product_id, max_id) as ( -- This is a CTE
select product_id, max(id) from sales group by product_id
)
select
p.name,
s.quantity
from products p
left join m on m.product_id = p.id
left join sales s on s.id = m.max_id
If you have an older MySQL, you can use a Table Expression:
select
p.name,
s.quantity
from products p
left join ( -- This is a table expression
select product_id, max(id) as max_id from sales group by product_id
) m on m.product_id = p.id
left join sales s on s.id = m.max_id

Get the lowest price for a product from a table of product prices per store

I am making a website to compare product prices between different stores. I have created a search function where I want to display the current lowest price and this is where I am a bit stuck.
I have a table Products with the basic information and a table product_store with the prizes in different stores for different products. Below is a basic schema of the database for these tables:
+-----------+ +---------------+
| products | | product_store |
+-----------+ +---------------+
| id | | product_id |
| name | | store_id |
+-----------+ | price |
| created_at |
+---------------+
The product_store table has multiple prices for the same product_id and store_id so I can create a price history.
Now I would like to create a query to get all products and their lowest price at the moment. So, you take the price for each store with the highest created_at, and from this collection I want to get the lowest value.
This is what I have tried so far:
select products.*, prices.price
from products
left join (
SELECT p1.product_id, min(p1.price) as price, p1.created_at
FROM product_store p1
WHERE p1.created_at = (SELECT max(created_at) FROM product_store p2 WHERE p2.store_id = p1.store_id
) as prices
on prices.product_id = products.id
I search for the highest created_at per store and product and get the lowest price for these rows. However this gives some very strange results where the prices get mixed up between the products and some products that have prices don't have any in the results.
Can someone help me to create a good query for this problem?
Thanks in advance. :)
Here is one method. It aggregates the product_store table to get the maximum created date for each store. Then it joins it back to that table to get price and finally does an aggregation in the outer query:
select p.*, min(ps.price)
from products p left join
(select ps.product_id, ps.store_id, max(created_at) as maxca
from product_store ps
group by ps.product_id, ps.store_id
) pssum
on pssum.product_id = p.id left join
product_store ps
on ps.product_id = pssum.product_id and
ps.store_id = pssum.store_id and
ps.created_at = pssum.maxca
group by p.id;
Your product_store table is an example of a slowly changing dimension. If it were set up with a eff_date and end_date (effective date and end date) columns, then the query would be easier to write and probably more efficient in terms of performance.

Complex query with many joins

I am trying to make one query, to get some statistic data from database.
My tables structure described here:
PRODUCTS
id | price | buy_price | vendor_code | ...
ORDERS
id | shipping_method_id | ...
ORDER_ITEMS
id | order_id | product_id | quantity | ...
SHIPPING_METHODS
id | cost | ...
SUPPLIERS
id | code | ...
I want to get data like this. In words, I am making reports on Product total income, expenses and quantity of buys in my ecommerce, and want them to group by supplier. I wrote this sql:
SELECT orders.id,
suppliers.code,
COUNT(products.id)*items.quantity buys,
SUM(products.price*items.quantity + shipping_methods.cost) sales,
SUM(products.buy_price*items.quantity) expenses
FROM `orders` orders
INNER JOIN `order_items` items ON items.order_id = orders.id
INNER JOIN `products` products ON items.product_id = products.id
INNER JOIN (SELECT DISTINCT suppliers.code FROM `suppliers`) suppliers
ON products.vendor_code LIKE CONCAT(suppliers.code, '%%')
INNER JOIN `shipping_methods` shipping_methods ON orders.shipping_method_id = shipping_methods.id
WHERE (
orders.delivery_date_to BETWEEN '2011-11-18' AND '2011-11-19'
)
GROUP BY suppliers.code, orders.id
ORDER BY buys DESC
this returns to me this data:
order_id code buys sales expenses
85 SB 4 1504 1111.32
84 VD 2 496 350.82
60 lg 2 1418 1052.31
88 SB 1 376 277.83
When I change GROUP BY suppliers.code, orders.id to GROUP BY suppliers.code, it returns almost correct data, I mean data is grouped by code, but counting is wrong. Admit that sales and expenses are correct
order_id code buys sales expenses
85 SB 8 1880 1389.15
60 lg 2 1418 1052.31
84 VD 2 496 350.82
If u see SB counted total 8 sales, but really there are only 5, as u can see in previous table. I'm sure I missed something in my query, but cant understand how to correct this.
PS field order_id are unused in my further scripts, I use it because django's Model.objects.raw() query does need to have primary key in result, don't really understand why
try this query.
SELECT t1.code, SUM(t1.buys), SUM(t1.sales) FROM (
SELECT orders.id,
suppliers.code,
COUNT(products.id)*items.quantity buys,
SUM(products.price*items.quantity + shipping_methods.cost) sales,
SUM(products.buy_price*items.quantity) expenses
FROM `orders` orders
INNER JOIN `order_items` items ON items.order_id = orders.id
INNER JOIN `products` products ON items.product_id = products.id
INNER JOIN (SELECT DISTINCT suppliers.code FROM `suppliers`) suppliers
ON products.vendor_code LIKE CONCAT(suppliers.code, '%%')
INNER JOIN `shipping_methods` shipping_methods ON orders.shipping_method_id = shipping_methods.id
WHERE (
orders.delivery_date_to BETWEEN '2011-11-18' AND '2011-11-19'
)
GROUP BY suppliers.code, orders.id
ORDER BY buys DESC
) AS t1
GROUP BY t1.code
Edit: I've forgotten SUM() parts. Just added, please retry if you've already tried.