I am constructing query to get the maximum price for same product.
I have table as
-----------------------------------------
| prod_id | price | user_id |
-----------------------------------------
| 4 | 25 | 1 |
| 4 | 38 | 2 |
| 4 | 41 | 3 |
| 7 | 100 | 1 |
| 7 | 95 | 2 |
-----------------------------------------
I am trying to get following output:
-----------------------------------------
| 4 | 41 | 3 |
-----------------------------------------
| 7 | 100 | 1 |
-----------------------------------------
I have constructed following query which is not right.
select * from user_bid group by prod_id having max(price);
Can someone guide me to get the query for desired results.
SELECT *
FROM user_bid
WHERE (prodid, price) IN
(
SELECT prodid, MAX(price)
FROM user_bid
GROUP BY prod_id
)
Here is an option using a join:
SELECT p1.*
FROM prod_id
INNER JOIN
(
SELECT prod_id, MAX(price) AS price -- this inner subquery finds the maximum
FROM user_bid -- price for each product group
GROUP BY prod_id
) p2
ON p1.prod_id = p2.prod_id AND -- and this join condition retains
p1.price = p2.price -- only records which have this maximum
-- price for each product group
And here is an option which uses a subquery:
SELECT p1.*
FROM prod_id p1
WHERE price = (SELECT MAX(p2.price) FROM prod_id p2 WHERE p1.prod_id = p2.prod_id)
For SQL Server
;WITH cte AS
(
SELECT prod_id,price,user_id,
ROW_NUMBER() OVER(PARTITION BY prod_id ORDER BY price desc) as rank
FROM table Name
)
SELECT prod_id,price,user_id
FROM cte
WHERE rank=1
Use the below query:
SELECT * FROM (SELECT * FROM user_bid ORDER BY price DESC) AS Temp
GROUP BY prod_id
Output:
Related
Write an SQL query to find the customer_number for the customer who has placed the largest number of orders.
Input:
Orders table:
+--------------+-----------------+
| order_number | customer_number |
+--------------+-----------------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 3 |
+--------------+-----------------+
Output:
+-----------------+
| customer_number |
+-----------------+
| 3 |
+-----------------+
my SQL:
select max(c.d),customer_number from (Select Count(order_number) as d,customer_number from Orders group by customer_number) as c
expected result:
[2,3]
actual result:
[2,1]
You could use a LIMIT query here:
SELECT customer_number, COUNT(*) AS num_orders
FROM Orders
GROUP BY customer_number
ORDER BY num_orders DESC
LIMIT 1;
Assuming you could have ties for two or more customers having the same maximum number of orders, then using RANK would be the easiest way on MySQL 8+:
WITH cte AS (
SELECT customer_number, COUNT(*) AS num_orders,
RANK() OVER (ORDER BY COUNT(*) DESC) AS rnk
FROM Orders
GROUP BY customer_number
)
SELECT customer_number, num_orders
FROM cte
WHERE rnk = 1;
I wanted to know if there's a way to join two or more result sets into one.
i have the following two queries
First query:
SELECT
CONCAT(day(db.prod_id.created_on),"-",month(db.prod_id.created_on),"-",year(db.prod_id.created_on)) as day_month_year,
db.country.country ,
count(concat(day(db.prod_id.created_on),"-",month(db.prod_id.created_on),"-",year(db.prod_id.created_on))) as count ,
COUNT(DISTINCT db.prod_id.email) AS MAIL
from db.prod_id
left join db.country on db.prod_id.branch_id = db.country.id
where db.prod_id.created_on > '2020-11-17' and (db.country.type = 1 or db.country.type = 2)
group by
concat(day(db.prod_id.created_on),"-",month(db.prod_id.created_on),"-",year(db.prod_id.created_on)),
db.country.country
order by db.prod_id.created_on
The second query:
select
CONCAT(day(db.prod_id.created_on),"-",month(db.prod_id.created_on),"-",year(db.prod_id.created_on)) as day_month_year,
db.country.country,
count(CONCAT(day(db.prod_id.created_on),"-",month(db.prod_id.created_on),"-",year(db.prod_id.created_on))) as count_BUY
from db.prod_id
left join db.prod_evaluations on db.prod_id.id = db.prod_evaluations.id
left join db.country on db.prod_id.branch_id = db.country.id
left join (Select prod_properties.prod_id, prod_properties.value From prod_properties Where prod_properties.property_id = 5) as db3 on db3.prod_id = db.prod_id.id
where db.prod_id.created_on > '2020-11-17'
and db3.value = 'online-buy' and db.prod_id.status_id <> 25
group by
concat(day(db.prod_id.created_on),"-",month(db.prod_id.created_on),"-",year(db.prod_id.created_on)),
db.country.country
order by db.prod_id.created_on
The first query give the following result:
+------------+---------+-------+------+
| day | Country | Count | Mail |
+------------+---------+-------+------+
| 17-11-2020 | IT | 200 | 100 |
| 17-11-2020 | US | 250 | 100 |
| 18-11-2020 | IT | 350 | 300 |
| 18-11-2020 | US | 200 | 100 |
+------------+---------+-------+------+
The second query give:
+------------+---------+-----------+
| day | Country | Count_BUY |
+------------+---------+-----------+
| 17-11-2020 | IT | 50 |
| 17-11-2020 | US | 70 |
| 18-11-2020 | IT | 200 |
| 18-11-2020 | US | 50 |
+------------+---------+-----------+
Now i want to merge these two result in one:
+------------+---------+-------+------+-----------+
| day | Country | Count | Mail | Count_BUY |
+------------+---------+-------+------+-----------+
| 17-11-2020 | IT | 200 | 100 | 50 |
| 17-11-2020 | US | 250 | 100 | 70 |
| 18-11-2020 | IT | 350 | 300 | 200 |
| 18-11-2020 | US | 200 | 100 | 50 |
+------------+---------+-------+------+-----------+
How can i perform this query?
I'm using mysql
Thanks
The simple way: You can join queries.
select *
from ( <your first query here> ) first_query
join ( <your second query here> ) second_query using (day_month_year, country)
order by day_month_year, country;
This is an inner join. You can also outer join of course. MySQL doesn't support full outer joins, though. If you want that, you'll have to look up how to emulate a full outer join in MySQL.
The hard way ;-) Merge the queries.
If I am not mistaken, your two queries can be reduced to
select
date(created_on),
branch_id as country,
count(*) as count_products,
count(distinct p.email) as count_emails
from db.prod_id
where created_on >= date '2020-11-17'
and branch_id in (select country from db.country where type in (1, 2))
group by date(created_on), branch_id
order by date(created_on), branch_id;
and
select
date(created_on),
branch_id as country,
count(*) as count_buy
from db.prod_id
where created_on >= date '2020-11-17'
and status_id <> 25
and prod_id in (select prod_id from prod_properties where property_id = 5 and status_id <> 25)
group by date(created_on), branch_id
order by date(created_on), branch_id;
The two combined should be
select
date(created_on),
branch_id as country,
sum(branch_id in (select country from db.country where type in (1, 2)) as count_products,
count(distinct case when branch_id in (select country from db.country where type in (1, 2) then p.email end) as count_emails,
sum(status_id <> 25 and prod_id in (select prod_id from prod_properties where property_id = 5 and status_id <> 25)) as count_buy
from db.prod_id
where created_on >= date '2020-11-17'
group by date(created_on), branch_id
order by date(created_on), branch_id;
You see, the conditions the queries have in common remain in the where clause and the other conditions go inside the aggregation functions.
sum(boolean) is short for sum(case when boolean then 1 else 0 end), i.e. this counts the rows where the condition is met in MySQL.
I have 2 columns in my pricing table: car_id and price
I want to
Group the records with same car_ids and sort these groups by price in itself. (namely, all records with the same car_id must be listed consecutively.)
I want to sort these groups by minimum price they include.
For example,
car_id | price
---------------
1 | 2
1 | 5
2 | 3
2 | 1
2 | 10
3 | 7
3 | 3
3 | 8
should be sorted like this:
car_id | price
---------------
2 | 1
2 | 3
2 | 10
1 | 2
1 | 5
3 | 3
3 | 7
3 | 8
How can I write a query that performs this operation? I am using MySQL V5.6.
You may use a subquery since the 5.6 does not support the window functions.
select *,
(
select min(price)
from datatab d2
where d1.car_id = d2.car_id
) min_price
from datatab d1
order by min_price, car_id, price
DBFIDDLE DEMO
You can use a subquery that returns the min price for each car_id in the ORDER BY clause:
select t.*
from tablename t
order by
(select min(price) from tablename where car_id = t.car_id),
car_id,
price
See the demo.
Or join the table to the subquery that returns all the min prices:
select t.*
from tablename t inner join (
select car_id, min(price) minprice
from tablename
group by car_id
) m on m.car_id = t.car_id
order by
m.minprice,
t.car_id,
t.price
See the demo.
Results:
| car_id | price |
| ------ | ----- |
| 2 | 1 |
| 2 | 3 |
| 2 | 10 |
| 1 | 2 |
| 1 | 5 |
| 3 | 3 |
| 3 | 7 |
| 3 | 8 |
You can use window functions in the order by:
select p.*
from pricing p
order by min(price) over (partition by car_id),
car_id;
The car_id handles the case when multiple car_ids have the same minimum price.
In older versions of MySQL, you can do something similar with a subquery:
select p.*
from pricing p
order by (select min(p2.price) from pricing p2 where p2.car_id = p.car_id),
car_id;
I have a table like so (I'm not sure how to format tables)
Category / Products / Purchases
1 | A | 12
1 | B | 13
1 | C | 11
2 | A | 1
2 | B | 2
2 | C | 3
Expected output:
1 | B | 13
2 | C | 3
However I keep on getting
1 | A | 13
2 | A | 3
ie. It just selects the first occurrence of the second column.
Here is my code:
SELECT Category, Products, MAX(Purchases) FROM myTable GROUP BY Category;
Use filtering in the where clause:
select t.*
from t
where t.purchases = (select max(t2.purchases) from t t2 where t2.category = t.category);
With NOT EXISTS:
select m.* from myTable m
where not exists (
select 1 from myTable
where category = m.category and purchases > m.purchases
)
See the demo.
Results:
| Category | Products | Purchases |
| -------- | -------- | --------- |
| 1 | B | 13 |
| 2 | C | 3 |
You can use row_number() to identify max purchase for each group or replace rownumber() to rank() if there are ties of max purchases for each group
Select Category, Products,
Purchases from (Select Category,
Products,
Purchases,
row_number() over (partition by
category, products order by
purchases desc) rn from table) t
where t.rn=1
)
I have the items_ratings table as follows:
items_ratings
+----+--------+---------+---------+---------------------+
| id | rating | user_id | item_id | created (DATETIME) |
+----+--------+---------+---------+---------------------+
| 1 | 20 | 1 | 12 | 2017-07-12 14:00:04 |
| 2 | 80 | 2 | 12 | 2017-07-12 15:32:12 |
| 3 | 50 | 1 | 15 | 2017-08-01 11:14:04 |
| 4 | 90 | 1 | 12 | 2017-08-02 19:23:19 |
| 5 | 60 | 2 | 15 | 2017-08-05 19:23:19 |
+----+--------+---------+---------+---------------------+
I need to retrieve the average value per item_id, using each user's most recent rating.
The following gives me the average rating for each item:
SELECT AVG(rating) FROM items_ratings
GROUP BY item_id
I have also identified that the following query gives me the most recent row for each user_id, by item_id.
SELECT MAX(created), user_id, item_id FROM items_ratings
GROUP BY user_id, item_id;
I am unsure of how I should combine these queries to yield my desired result.
You could use a select from join table with max created by user_id
select item_id, avg( rating) from (
select * from items_ratings a
inner join (
SELECT MAX(created) t_created, user_id
FROM items_ratings
GROUP BY user_id
) t on t.user_id = a.user_id and t.t_created = a.created
) t1
group by item_id
The inner select get the max created by user_id, the other get all the rows that macht and the outer buil the avg on this group by item_id
and with the your new condition on item_id you could use
select item_id, avg( rating) from (
select * from items_ratings a
inner join (
SELECT MAX(created) t_created, user_id, item_id
FROM items_ratings
GROUP BY user_id, item_id
) t on t.user_id = a.user_id and t.t_created = a.created and t.item_id = a.item_id
) t1
group by item_id