Combine latest records with table - mysql

I am using mysql and I am having the following two tables:
Products:
| id | name |
|----|-----------|
| 1 | Product 1 |
| 2 | Product 2 |
| 3 | Product 3 |
Prices:
| id | Product_id | created_at | prices |
|----|------------|---------------------|--------|
| 1 | 1 | 2017-12-23 08:32:11 | 10 |
| 2 | 1 | 2017-11-21 03:33:10 | 12 |
| 3 | 2 | 2017-12-23 08:32:11 | 43 |
| 4 | 2 | 2017-11-21 03:33:10 | 23 |
| 5 | 3 | 2017-12-23 08:32:11 | 78 |
| 6 | 3 | 2017-11-21 03:33:10 | 34 |
If I do:
SELECT * FROM prices WHERE prices.id IN ( SELECT MAX(prices.id) FROM prices GROUP BY prices.created_at )
This gives me the last prices for each product_id:
| id | Product_id | created_at | prices |
|----|------------|---------------------|--------|
| 1 | 1 | 2017-12-23 08:32:11 | 10 |
| 3 | 2 | 2017-12-23 08:32:11 | 43 |
| 5 | 3 | 2017-12-23 08:32:11 | 78 |
I would like to have as final result all Products with the latest prices, which would look like the following:
| id | name | product_id | created_at | prices |
|----|-----------|------------|---------------------|--------|
| 1 | Product 1 | 1 | 2017-12-23 08:32:11 | 10 |
| 2 | Product 2 | 2 | 2017-12-23 08:32:11 | 43 |
| 3 | Product 3 | 3 | 2017-12-23 08:32:11 | 78 |
However, I am not sure how to combine:
select * from products
and
SELECT * FROM prices WHERE prices.id IN ( SELECT MAX(prices.id) FROM prices GROUP BY prices.created_at )
I highly appreciate your replies!

Assuming your first query is giving you expected result, just use join.
SELECT p.*,d.name FROM prices p
inner join product d
on d.id=p.product_id
WHERE
p.id IN
( SELECT MAX(prices.id) FROM prices GROUP BY prices.created_at )
If you believe that there are product id in price which are not mapped in product then use left join instead of inner join.

I think you have get max total price with product name so below is query according your given tables
select prices.id, products.id,products.product, sum(prices.prices) as Totalprices from prices join products on prices.id=products.id group by prices.id order by Totalprices desc limit 1
Hope it help you

Assuming that the latest prices are the most recent created ones and depicted by prices.created_at value, to get the latest prices you could better rely on prices.created_at, instead of assuming chronological ordering by mean of prices.id (autoincrement), as in:
SELECT products.id, products.name, prices.created_at, prices.prices
FROM products
INNER JOIN prices ON products.id=prices.product_id
INNER JOIN
(SELECT product_id, MAX(created_at) AS created_at FROM prices GROUP BY product_id) AS LATEST_PRICES
on prices.product_id=LATEST_PRICES.product_id
-- WHERE prices.created_at = LATEST_PRICES.created_at
AND prices.created_at = LATEST_PRICES.created_at

Related

MySQL: How to select min() using subquery and joins

I have 3 MySQL tables. I've trimmed them down to show just the important columns
items
id | title |
1 | Hamlet |
2 | Romeo and Juliet |
3 | The Merchant of Venice |
listings
id | item_id | condition |
1 | 1 | Mint |
2 | 1 | Used - Good |
3 | 2 | New |
4 | 2 | Mint |
5 | 2 | Used - Poor |
6 | 3 | Used - Poor |
7 | 3 | Used - Good |
8 | 3 | Used - Good |
itemListings_variations
id | listing_id | price
1 | 1 | 20.00
2 | 1 | 10.00
3 | 1 | 5.00
4 | 2 | 6.00
5 | 2 | 5.50
6 | 3 | 2.00
7 | 4 | 12.00
8 | 5 | 3.00
9 | 6 | 9.00
If e.g. I search for Romeo and Juliet, it should return:
item_id | title | min_price
2 | Romeo and Juliet | 2.00
So far I have two queries which somehow need combining via subqueries and joins. I have:
SELECT
i.id AS item_id,
i.title
FROM items i
WHERE MATCH (i.title) AGAINST (:search)
also:
SELECT
l.item_id,
v.listing_id,
MIN(price) AS min_price
FROM itemListings_variation v, itemListings l
WHERE v.listing_id = l.id
GROUP BY v.listing_id
Try this -
SELECT i.id, i.title, MIN(price)
FROM items i
INNER JOIN listings l ON i.items = l.item_id
INNER JOIN itemListings_variations il ON l.id = il.listing_id
GROUP BY i.id, i.title
Hope this helps.
No group by is needed as calling min(price) will return the row with the lowest price.
select t1.id, title, min(price) from
(select * from items where title = 'Romeo and Juliet' ) as t1
left join listings on t1.id = listings.item_id
left join itemlistings_variations on listing_id = listings.id;
Tested on my test server.

select sum() from multiple table with same column

I have a table for product, sales_item and a stock with following structure
Product table:
+----+-----+-------------+
| id |name |description |
+----+-----+-------------+
| 1 |Pr1 |prod1 |
+----+-----+-------------+
| 2 |Pr2 |prod2 |
+----+-----+-------------+
| .. |... |..... |
+----+-----+-------------+
sales_item_details table
+-----+----------+------------+-----+
| id | sales_id | product_id | qty |
+-----+----------+------------+-----+
| 517 | 211 | 1 | 200 |
+-----+----------+------------+-----+
| 518 | 211 | 1 | 120 |
+-----+----------+------------+-----+
and production
+----+------------+-------+
| id | product_id | qty |
+----+------------+-------+
| 1 | 1 | 20 |
| 2 | 2 | 200 |
| 3 | 1 | 20 |
| 4 | 3 | 30 |
| 5 | 9 | 30 |
| 6 | 65 | 10 |
| 7 | 65 | 50 |
| 8 | 71 | 10 |
| 9 | 71 | 10 |
| 10 | 71 | 10 |
+----+------------+-------+
And now I am creating multiple database with same table defination and need to maintain stock
production table and product table will be maintained from single database
only sales_item_details table will be different but product id will same
So how will be the query to get SUM(qty) of sales item details and view the inventory in stock
I have tried this:
SELECT
`pr`.`id`,
`pr`.`name`,
sl.size,
IFNULL(SUM(s.qty), 0) AS sales,
IFNULL((SELECT SUM(qty) FROM production st WHERE st.product_id = `pr`.`product-id`), 0) AS stock_added
FROM products pr
LEFT JOIN (
SELECT qty, product_id FROM db1.sales_item_details
UNION ALL
SELECT qty, product_id FROM db2.sales_item_details
) s ON pr.`id` = s.product_id
LEFT JOIN size_list sl ON sl.id = `pr`.`product-size`
GROUP BY s.product_id
ORDER BY sales DESC
but getting the product which is sold
Any help will be appriciated
1st I created a view holding all sales items grouped by product id in the main database:
CREATE OR REPLACE VIEW unit_sold_all AS
SELECT
p.`product-id` AS product_id,
(
(SELECT IFNULL(SUM(s0.qty), 0) FROM db_1.sales_item_details s0 WHERE s0.product_id = p.`product-id`) +
(SELECT IFNULL(SUM(s1.qty), 0) FROM db_2.sales_item_details s1 WHERE s1.product_id = p.`product-id`) +
(SELECT IFNULL(SUM(s2.qty), 0) FROM db_3.sales_item_details s2 WHERE s2.product_id = p.`product-id`) +
(SELECT IFNULL(SUM(s3.qty), 0) FROM db_4.sales_item_details s3 WHERE s3.product_id = p.`product-id`) +
(SELECT IFNULL(SUM(s4.qty), 0) FROM db_5.sales_item_details s4 WHERE s4.product_id = p.`product-id`)
) as total_unit_sales
FROM products p
Then in another sql, I selected the sum of the sales.
PS: I answered this question myself because this might need by another person in the future.

SQL select count from multiple tables

I'm a starter at SQL and I have the following tables, ORDER_PRODUCTS, listing the products of an order and EXCHANGE_PRODUCTS, listing products that will be exchanged.
Both have the same fields, and I need to make a selection counting the amount of products in both tables, distinguishing them by the order_id, does anyone knows how I can do this?
ORDER_PRODUCTS
+-----+------------+----------+---------+
| id | product_id | order_id | amount |
+-----+------------+----------+---------+
| 1 | 5 | 1 | 2 |
| 2 | 7 | 1 | 1 |
| 3 | 13 | 5 | 1 |
| 4 | 18 | 8 | 3 |
| 5 | 45 | 11 | 4 |
+-----+------------+----------+---------+
EXCHANGE_PRODUCTS
+-----+------------+----------+---------+
| id | product_id | order_id | amount |
+-----+------------+----------+---------+
| 1 | 5 | 1 | 1 |
| 2 | 7 | 1 | 2 |
| 3 | 13 | 5 | 1 |
| 4 | 3 | 8 | 2 |
| 5 | 2 | 11 | 1 |
+-----+------------+----------+---------+
You want to use union all to combine the tables and then aggregate them. I might recommend:
select order_id, sum(ordered) as ordered, sum(exchanged) as exchanged,
sum(exchanged + ordered) as total
from ((select order_id, amount as ordered, 0 as exchanged
from order_products
) union all
(select order_id, 0 as ordered, amount as exchanged
from exhange_products
)
) oe
group by order_id;
It is important to use union all rather than union, because union removes duplicates (which can result in bad numbers). Union also incurs overhead that is unnecessary.
And, by "count amount" I assume you really mean to take the sum.
I think this query should do what you Need:
select sum(amount), order_id from (
select amount,order_id from order_products
union
select amount,order_id from Exchange_products)
group by order_id

Implementing a complex query in MySQL

I have 3 tables:
table products
table sub products
table stock.
I want to join these tables like in the result table below. In fact, I want All products that have least price and have count greater than zero and inserted as latest records!
How can I do the query?
more explain:
table product
----------------------------------
pid | title | desc | content |
----------------------------------
1 | lumia 920| ..... | ...... |
----------------------------------
2 | galaxys6 | .... | ...... |
----------------------------------
table sub_product
------------------------
subid |pid| name |
------------------------
1 | 1 | yellow |
------------------------
2 | 1 | black |
------------------------
3 | 2 | 32 GB |
table stock
-----------------------------------------------
sid |subid| price | count | inserted_date |
-----------------------------------------------
1 | 1 | 100 | 5 | 2015-01-01 |
-----------------------------------------------
2 | 1 | 150 | 9 | 2015-01-02 |
-----------------------------------------------
3 | 1 | 100 | 0 | 2015-02-02 |
-----------------------------------------------
4 | 2 | 111 | 1 | 2015-02-21 |
-----------------------------------------------
5 | 3 | 50 | 7 | 2015-02-01 |
-----------------------------------------------
6 | 3 | 10 | 4 | 2015-03-06 |
-----------------------------------------------
7 | 3 | 400 | 9 | 2015-06-06 |
-----------------------------------------------
table result
------------------------------------------------------------
pid |subid| title | name | price | count | inserted_date
------------------------------------------------------------
1 | 2 |lumia 920| black | 111 | 1 | 2015-02-21
------------------------------------------------------------
2 | 3 |galaxy s6| 32 GB | 10 | 4 | 2015-03-06
------------------------------------------------------------
as you see in product table we have two items lumia 920 and galaxy s6
and in sub_product we have 3 items that related to products.
also in stock I saved all modication of price and count of each item
so I want return latest modification of each sub_product as current state of it sub_prodct that has least price as result
but if count was zero should return another sub_product with mentioned conditions.
Select * From stock s Join sub_product sp On s.sub_productid = sp.sub_productid Join product p On p.productid = sp.productid
Where s.counte > 0 And s.date_insert in (Select MAX(date_insert) as d From stock ss
where s.sub_productid = ss.sub_productid group by sub_productid)
This query will return the all products that have least price and have count greater than 0 and latest records.
SELECT p.pid, sp.subid, p.title, sp.name, s.price, s.count, s.inserted_date
FROM product p
INNER JOIN sub_product sp ON sp.pid = p.pid
INNER JOIN stock s ON s.subid = sp.subid
WHERE s.count > 0
GROUP BY p.title
ORDER BY s.inserted_date DESC, s.price ASC
Try something like this:
SELECT prod.title, prod.desc, subProd.spid, subProd.pid, subProd.name, stk.price, stk.discount, stk.count, stk.inserted_date
FROM products AS prod
INNER JOIN sub_products AS subProd ON prod.pid = subProd.pid
INNER JOIN stock AS stk ON subProd.spid = stk.spid
AND stk.count > 0
AND stk.spid = (select spid from stock order by inserted_date desc limit 1)

SUM rows only if it does not have one of the multivalued values

Movies table:
+----+------+---------+
| id | title | price |
+----+------+---------+
| 1 | movie1 | 20 |
| 2 | movie2 | 15 |
| 3 | movie3 | 25 |
| 4 | movie4 | 10 |
+----+------+---------+
Categories table:
+-----+--------+
| idd | cat |
+-----+--------+
| 1 | horror |
| 1 | comedy |
| 2 | drama |
| 2 | sci-fi |
| 3 | action |
| 4 | sci-fi |
+-----+--------+
I want to make a query to sum the prices of all the movies except the ones that have 'sci-fi' as one of its categories.
I have tried this:
select count(distinct id) as no_of_movies, sum(price) as price
from (select distinct id,price
from movies,categories
where id=idd and not cat='sci-fi') as tt;
But it only works with the movies that have only one category, like 'movie4'.
It still sums 'movie2' as 'drama'.
So how can I also skip 'movie2' so that the output will be 45 instead of 60?
try this:
select count(distinct id) as no_of_movies, sum(price) as price
from (select distinct id,price
from movies,categories
where id=idd and id not in (select idd
from categories
where cat = 'sci-fi')) as tt;