How to get last 5 unique product IDs? - mysql

I have a table of orders. Each order is linked to one or more basket items.
Basic code:
SELECT * FROM Orders o JOIN OrderItems oi ON o.OrderNumber = oi.OrderNumber
I can limit to the last 5 items by doing this:
ORDER BY oi.CreatedDate DESC LIMIT 5
However, in some cases the user has placed multiple orders across the same products. e.g.
OrderNo ItemNo ProductId
1 1 70
1 2 20
2 1 80
2 2 30
3 1 10
4 1 90
5 1 10
6 1 40
7 1 50
8 1 100
9 1 10
10 1 30
11 1 10
12 1 60
If I get the last five items, I'd end up with 60, 10, 30, 10, 100. What I actually want is to get the last 5 unique product IDs - so that'd be 60, 10, 30, 100, 50. What would the SQL for this be?
Edited
If I use GROUP BY I get 60, 100, 50, 40, 90. Where is 30?

Try:
select ProductID from
(select ProductID, max(OrderNo)
from Orders
group by ProductID
order by 2 desc) sq
limit 5

USE `
GROUP BY Product ORDER BY Order DESC LIMIT 5
`

Just add GROUP BY Product
SELECT *
FROM Orders o
JOIN OrderItems oi ON o.OrderNumber = oi.OrderNumber
GROUP BY o.Product
ORDER BY oi.CreatedDate DESC LIMIT 5

EDIT: the problem is that MySql does group by before order by. A trick to fool it is:
SELECT * FROM
(
SELECT
O.OrderNumber,
oi.ItemNo,
oi.Productid
FROM
orders o
JOIN
OrderItems oi ON o.OrderNumber = oi.OrderNumber
ORDER BY
oi.CreateDate DESC
) AS fool_mysql
GROUP BY
ProductId
LIMIT 5;
That is, do the ordering BEFORE the grouping.

Related

Select multiple tables with only unique users and ordered by latest id

I have 2 tables, first one is called members:
id name show
1 John 1
2 Wil 1
3 George 1
4 Chris 1
Second is called score:
id user_id score
1 1 90
2 1 70
3 2 55
4 3 30
5 3 40
6 3 100
7 4 30
user_id from score is the id of members.
What I want is to show a scorelist with unique members.id, ordered by score.score and order by the latest score.id.
I use the following code:
SELECT members.id, members.show, score.id, score.user_id, score.score FROM members
INNER JOIN score ON score.user_id = members.id
WHERE members.show = '1'
GROUP BY score.user_id
ORDER BY score.score DESC, score.id DESC
The output is not ordered by the latest score.id, but it does show only unique user_id's:
id user_id score
1 1 90
3 2 55
4 3 30
7 4 30
It should be like:
id user_id score
6 3 100
2 1 70
3 2 55
7 4 30
I hope you can help me
You could use:
with cte as (
select id,
user_id,
score,
row_number() over(partition by user_id order by id desc) as row_num
from score
) select cte.id,user_id,score
from cte
inner join members m on cte.user_id=m.id
where row_num=1
order by score desc;
Demo
If your MySQL server doesn't support windows function, use:
select s.id,s.user_id,s.score
from score s
inner join members m on s.user_id=m.id
where s.id in (select max(id) as id
from score
group by user_id
)
order by score desc;
Demo

Use aggregate functions with group by from several tables

I have the following tables to allow the subscriber to sell products through the application
Order Table
OrderId
Date
1
2021-07-10
2
2021-08-24
Approval table
ApprovalId
OrderId
Status
SellerId
1
1
Accepted
10
2
1
Rejected
20
3
2
Accepted
30
Item table
ItemId
OrderId
Price
Qty
SellerId
1
1
620$
1
10
2
1
150$
2
10
3
1
410$
1
20
4
2
220$
1
30
what i want is to display the income revenue for > only who accept the order
Date
Sales
Seller_Part 90%
Net_Sales 10%
2021-07-10
770$
693$
77$
2021-08-24
220$
198%
22$
I tried using aggregate functions with group by but the result include rejected order also
select o.date
,sum(i.price * i.qty) sales
,sum(i.price * i.qty) * 0.90 Seller_Part90%
,sum(i.price * i.qty) * 0.10 Net_Sales10%
from Order o
join Approval a
on o.orderId = a.OrderId
and a.status= 'Accepted'
join Items i
on a.sellerid = i.sellerid
and a.orderid = i.orderid
group by o.date

SQL limit SELECT but not JOIN

I'm implementing pagination on my BD. My problem is when I want limit the SELECT statement but not the JOIN. Example, a product can got many prices:
SELECT * FROM product
LEFT JOIN price ON product.id == price.id_product
LIMIT 20
But I want to get 20 products with each one with their prices. How I can limit the statement SELECT, but not LEFT JOIN.
Example:
product price.id price.id_pruct price.price
1 1 1 50
2 2 1 30
3 3 1 40
4 1 20
5 2 30
SELECT * FROM product
LEFT JOIN price ON product.id == price.id_product
LIMIT 3
Return:
product price.id id_prodcut price
1 1 1 50
1 2 1 30
1 3 1 40
But I Want
product price.id id_prodcut price
1 1 1 50
1 2 1 30
1 3 1 40
1 4 1 20
2 5 2 30
3 . . .
Three products (limit 3)
Thanks. I hope you can help me.
Modify your query to limit the number of product rows before joining it to the price table. This means we want to to join the results of a query to a table, or in other words, we write a query containing a subquery:
SELECT *
FROM (
SELECT *
FROM product
ORDER BY id_product
LIMIT 3
) p
LEFT JOIN price ON p.id = price.id_product
Hope that helps.
I would write a subquery to get the three first products (or whatever condition you choose) like this:
SELECT id
FROM product
ORDER BY id
LIMIT 3;
Once I have that, I can select everything from the price table as long as the id is in that subquery. You can do this using a join:
SELECT p.*
FROM price p
JOIN(
SELECT id
FROM product
ORDER BY id
LIMIT 3) tmp ON tmp.id = p.product_id;
Here is an SQL Fiddle example using your sample data, and I also added a row that won't be returned so you can see that it works.

how to get total order price using mysql?

there are two tables one is order and 2nd one is order_details respectively,
order table
order_id order_name
1 shoes
2 wallet
3 socks
4 bats
order_details table
order_details_no order_id(foregin key) order_price
1 1 25
2 1 55
3 2 65
4 4 30
5 4 60
My question is, I want result set which includes order_id, order total price in ascending order (eg order 1 total is 80,order 4 total is 90 )
How to get this ?
select order_id,
sum(order_price) as total_sum
from order_details
group by order_id
order by total_sum asc
Select
order.order_name,
sum(order_details.order_price) as price
from order
join order_details
on order_details.order_id=order.order_id
group by
order.order_id
order by
price desc

MySQL Query limit 3 or more if last 3 are equal?

I need to limit my result to 3 row (an example), but if 3rd result is equal to 4th, print also 4th, and so on.
To explain: from this table
id punteggio
1 100
2 200
3 70
4 100
5 54
6 201
7 200
if I do
SELECT * FROM table ORDER BY punteggio DESC LIMIT 3
i need in every case to print following situation:
id punteggio
6 201
2 200
7 200
1 100
4 100
Because my "three" best points are in reality 5 of 7, cause 2 and 7 have same points, like 1 and 4...
I dont'know in advance min and max points, otherwise i would do
"WHERE punteggio >= 100"
Thank you very much!
UPDATE
Unfortunately my scenario changed:
punteggio born from SUM from another table:
id idPersona punteggio
1 1 30
2 1 -10
3 2 50
4 3 60
5 2 -10
6 3 150
7 1 190
and so on...
i've tried do:
SELECT persone.nome,
SUM(transazioni.importoFinale) AS punti
FROM transazioni
INNER JOIN persone ON persone.idPersona = transazioni.idPersona
INNER JOIN
(SELECT DISTINCT(SUM(transazioni.importoFinale)) AS punti,
persone.nome
FROM transazioni
INNER JOIN persone on persone.idPersona = transazioni.idPersona
GROUP BY persone.idPersona
ORDER BY punti DESC
LIMIT 3) subq ON transazioni.punti = subq.punti
ORDER BY punti DESC
but it doens't function...
Thank you to all!
Use a subquery join to get the DISTINCT set of 3 greatest values for punteggio and join it against the main table to retrieve all rows that have those values.
SELECT
id,
punteggio
FROM
yourtable
/* subquery gets the top 3 values only */
/* and the INNER JOIN matches it to all rows in the main table having those values */
INNER JOIN (
SELECT DISTINCT punteggio as p
FROM yourtable
ORDER BY punteggio DESC
LIMIT 3
) subq ON yourtable.punteggio = subq.p
ORDER BY punteggio DESC
Here's a demo on SQLFiddle.com
SELECT id, punteggio
FROM yourtable
WHERE punteggio IN (
SELECT * FROM (
SELECT DISTINCT punteggio
FROM yourtable
ORDER BY punteggio DESC
LIMIT 3
) AS temp
);
Note that the select * is present to work around mysql not supporting limits in subqueries in an IN() clause.