Select only one row while doing groupby in mysql - mysql

T have the following table:
mid pid price
1 100 10
1 200 10
1 300 10
1 400 10
2 500 20
2 600 30
2 700 20
3 800 40
3 900 50
I want to find the least priced pid for each mid.
for that I was querying this code.
SELECT t1.mid,t1.pid
FROM tableName t1
JOIN (
SELECT mid, min(price) as min_price
FROM tableName
GROUP BY mid
) as t2 on t1.mid = t2.mid and t1.price = t2.min_price;
Ideally it should give result, but in my case in each group there are multiple pid having same price. so it is printing all the result.
but I just want to limit 1 row for each mid.
Is there any way to do this?
I have a
sqlfiddle demo

select s.mid,s.pid,s.price
from
(
SELECT t1.mid,t1.pid,t1.price,
if (t1.mid <> #p, #rn:=1,#rn:=#rn+1) rn,
#p:=t1.mid p
FROM (select #rn:=0,#p:=0) rn,t t1
order by t1.mid,t1.price,t1.pid
) s where s.rn = 1

TRY THIS: http://www.sqlfiddle.com/#!2/e2244c/71
SELECT t1.mid, MIN(DISTINCT t1.pid) AS Expr1
FROM tableName as t1
INNER JOIN
tableName AS tableName_1 ON t1.mid = tableName_1.mid
GROUP BY t1.mid
ORDER BY MIN(DISTINCT t1.pid) DESC

Try this:
select t1.*
from tablename t1
inner join (select mid, min(pid) min_pid from
(select t1.mid,t1.pid
FROM tablename t1
inner join (select mid,
min(price) as min_price
FROM tablename
GROUP BY mid) t2 on t1.mid = t2.mid
and t1.price = t2.min_price) t
group by mid) t2 on t1.mid = t2.mid
and t1.pid = t2.min_pid
;
It produces rows with minimum price and minimum pid.

It's works:
SELECT t1.mid,t1.pid FROM tableName t1
INNER JOIN (
SELECT mid AS mid1, pid AS pid1, min(price) as min_price FROM tableName GROUP BY mid
) as t2
on t1.mid = t2.mid1 and t1.price = t2.min_price and t1.pid = t2.pid1;

Related

How do I find the users biggest donation? without aggregate functions

For example given
table1
userId donation
1 50
1 150
1 340
1 20
2 85
2 15
I want
userId donation
1 340
2 85
I thought about cross joining them and see which was bigger but don't know what to do after this
SELECT * FROM
table1 as T1 cross join table1 as T2
WHERE
T1.userId = T2.userId
and
T1.donation > T2.donation
I think you are looking for something like this:
select *
from table1 T1
where not exists (
select 1
from table1 T2
where T2.userId=T1.userId and T2.donation > T1.donation
)
or the equivalent join:
select *
from table1 T1
left join table1 T2 on T2.userId=T1.userId and T2.donation > T1.donation
where T2.userId is null
If there are two rows with the same donation, both of them will be selected. If you don't want that, also compare primary key columns or some other unique keys:
T2.userId=T1.userId and (T2.donation,T2.primarykeycol1,T2.primarykeycol2) > (T1.donation,T1.primarykeycol1,T1.primarykeycol2)
You can use a self join and then compare the highest donation with the records of secondary table but same user.
SELECT T1.userId, T1.donation
FROM table1 T1
LEFT JOIN table1 T2 ON T1.userId = T2.userId AND T1.donation < T2.donation
WHERE T2.id IS NULL;
MySQL 8
WITH s1 AS (
SELECT userId,
donation,
RANK() OVER (PARTITION BY userId ORDER BY donation DESC) AS `Rank`
FROM table1
)
SELECT s1.userId, s1.donation
FROM s1
WHERE s1.`Rank` = 1;

Join 4 Tables to find total and sort by total

i have 3 tables
1) users
2) user_likes
3) user_pictures
4) user_pucture_likes
users(id, name)
user_likes(id, user_id, like)
user_pictures(id, user_id, filename)
user_picture_likes(id, user_picture_id, like)
what i am trying to do is to sort the user on the total like on user_like + user_picture_like
I am not good with joining more than 2 tables.
i got upto here
SELECT t2.user_id, sum(t1.total_likes) as image_likes from user_pictures as t2 JOIN (
SELECT sum(like_status) as total_likes, user_picture_id FROM `user_picture_likes` GROUP BY user_picture_id ORDER BY total_likes DESC
)as t1
ON t1.user_picture_id = t2.id GROUP BY t2.user_id ORDER BY image_likes DESC
and how do i proceed from here?
Try this
SELECT T1.Id AS UserID, SUM(T2.like), Tmp.filename AS Image, Tmp.Imageslikes
FROM users T1
LEFT JOIN user_likes T2 ON T1.Id = T2.user_id
LEFT JOIN (
SELECT T3.user_id, T3.filename, SUM(T4.likes) Imageslikes
FROM user_pictures LEFT JOIN user_picture_likes T4 ON T3.Id = T4.user_picture_id
GROUP BY T3.user_id, T3.filename
)Tmp ON T1.Id = Tmp.user_id

mySQL - SUM of column

I have 2 tables
table 1
id product
1 P1
2 P2
table 2
id amount product_t1
1 100 P1
2 200 P1
3 300 P2
4 400 P1
5 500 P2
I want my output to be:
product totalAmount(sum of amount)
P1 700
P2 800
EDIT: Here is my query so far
SELECT T1.product, SUM(T2.amount)
FROM table1 T1
INNER JOIN table2 T2
ON T1.product = T2.product_t1
Thanks!
you should use group by
SELECT T1.product, SUM(T2.amount)
FROM table1 T1
INNER JOIN table2 T2
ON T1.product = T2.product_t1
GROUP BY product
Since you're not using foreign keys you don't even need the table 1 for the desired result.
SELECT
product_t1 AS product,
SUM(amount) AS totalAmount
FROM table2
GROUP BY product_t1
What you're missing is the GROUP BY statement in order to get a separate row for each individual product
SELECT T1.product, SUM(T2.amount)
FROM table1 T1
INNER JOIN table2 T2
ON T1.product = T2.product_t1
GROUP BY product T1.product
Use the GROUP BY tag . Group by helps to group your result via value of product
Try to play with GROUP BY and AS
SELECT product_t1 as product, SUM(amount) AS totalAmount FROM table2
GROUP BY product
https://dev.mysql.com/doc/refman/5.7/en/group-by-modifiers.html
OR add to your code group by
SELECT T1.product, SUM(T2.amount)
FROM table1 T1
INNER JOIN table2 T2 ONT1.product = T2.product_t1
Gruop by T1.product

Limit on multiple table union

I've this mysql query with a limit on each select, but I want a limit of 1 on the complete query too. I've tried to build a Select around the whole query too, but it still goes through all the tables, even if there's a result in the first one so the duration is the same. I want the query to stop as soon as it gets a result. Is there any solution for this?
(SELECT count(*) FROM table1 i JOIN table1item it where it.columnId = 2 LIMIT 1)union
(SELECT count(*) FROM table2 i JOIN table2item it where it.columnId = 2 LIMIT 1)union
(SELECT count(*) FROM table3 i JOIN table3item it where it.columnId = 2 LIMIT 1)union
(SELECT count(*) FROM table4 i JOIN table4item it where it.columnId = 2 LIMIT 1)union
(SELECT count(*) FROM table5 i JOIN table5item it where it.columnId = 2 LIMIT 1)union
(SELECT count(*) FROM table6 i JOIN table6item it where it.columnId = 2 LIMIT 1)union
(SELECT count(*) FROM table7 i JOIN table7item it where it.columnId = 2 LIMIT 1)
Add UNION ALL to be sure you'll get results from all table if they are equal.
(SELECT count(*) FROM table1 i JOIN table1item it where it.columnId = 2) UNION ALL
(SELECT count(*) FROM table2 i JOIN table2item it where it.columnId = 2) UNION ALL
(SELECT count(*) FROM table3 i JOIN table3item it where it.columnId = 2) UNION ALL
(SELECT count(*) FROM table4 i JOIN table4item it where it.columnId = 2) UNION ALL
(SELECT count(*) FROM table5 i JOIN table5item it where it.columnId = 2) UNION ALL
(SELECT count(*) FROM table6 i JOIN table6item it where it.columnId = 2) UNION ALL
(SELECT count(*) FROM table7 i JOIN table7item it where it.columnId = 2)
LIMIT 1
A workmate found a solution which really reduces the query time (0.25 instead of 0.75 in my test case):
SELECT
case
when count(*) > 0
then 1
else (
SELECT
case
when count(*) > 0
then 1
else (
SELECT
case
when count(*) > 0
then 1
else (
SELECT
case
when count(*) > 0
then 1
else (
SELECT
case
when count(*) > 0
then 1
else (
SELECT
case
when count(*) > 0
then 1
else (
SELECT
case
when count(*) > 0
then 1
else 0
end as result
FROM table1 i JOIN table1item it where it.fooId = 1 LIMIT 1
)
end as result
FROM table2 i JOIN table2item it where it.fooId = 1 LIMIT 1
)
end as result
FROM table3 i JOIN table3item it where it.fooId = 1 LIMIT 1
)
end as result
FROM table4 i JOIN table4item it where it.fooId = 1 LIMIT 1
)
end as result
FROM table5 i JOIN table5item it where it.fooId = 1 LIMIT 1
)
end as result
FROM table6 i JOIN table6item it where it.fooId = 1 LIMIT 1
)
end as result
FROM table7 i JOIN table7item it where it.fooId = 1 LIMIT 1

Ordering of grouped rows in mysql

SELECT t1.item_id, t1.item, t1.created, t1.owner, t1.type, t1.fld, t2.tag
FROM items AS t1
INNER JOIN tagged AS t2 ON t1.item_id = t2.item_id
WHERE tag
IN ('how', 'jkas', 'bodor', 'zimp', 'ctuo', 'sjex', 'kek'
)
GROUP BY item_id
ORDER BY t1.created DESC
LIMIT 0 , 100
How to order items by how many matches they have with IN TAG? I went really deep in manual and I couldn't find the answer and I got lost in stuff I don't understand.
You can use COUNT and put the results in a subquery:
SELECT *
FROM (
SELECT t1.item_id, t1.item, t1.created, t1.owner,
t1.type, t1.fld, t2.tag, COUNT(DISTINCT t2.tag) tagCount
FROM items AS t1
INNER JOIN tagged AS t2 ON t1.item_id = t2.item_id
WHERE tag IN ('how', 'jkas', 'bodor', 'zimp', 'ctuo', 'sjex', 'kek')
GROUP BY item_id
) t
ORDER BY tagCount DESC, created DESC
LIMIT 0 , 100