In mysql. I want to get some the largest counted review_id and mention.
below table is raw data
>> table Named: topic_id_review_id
id topic_id review_id
+-------+-------------+-------------+
1 1 1
2 1 1
3 1 1
4 2 1
5 4 1
6 3 2
7 5 2
8 2 3
9 2 3
10 3 3
11 3 1
12 5 4
13 5 1
14 6 5
16 7 7
17 7 7
18 7 7
...
....
**I want to get the top of four(4) topics about each of review_id.
>> wanted!!
topic_id review_id
+-------------+-------------+
1 1
2 1
3 1
4 1
3 2
5 2
2 3
3 3
5 4
...
....
like above table, I want to top 4 topics in Every review_id.
I have already tried some code. but all of thing is not good results...
SELECT
tr1.topic_id, tr1.review_id
FROM topic_id_review_id tr1
WHERE review_id IN (1,2,3)AND(
SELECT COUNT(*)FROM topic_id_review_id tr2
WHERE tr2.review_id = tr1.review_id) < 4;
SELECT
COUNT(*) AS `count`
FROM topic_id_review_id tr2
WHERE tr2.review_id = 1
GROUP BY topic_id, review_id
order by `count` DESC LIMIT 4;
maybe your guy, this not difficult... but as beginner to me...
it is not simple. so please let me know to to solve it! thanks
One way that works in all versions of MySql is the use of a correlated subquery in the WHERE clause which counts the number of topic_ids for each review_id:
select
t.topic_id, t.review_id
from (
select min(id) id, topic_id, review_id
from topic_id_review_id
group by topic_id, review_id
) t
where (
select count(*) from topic_id_review_id
where review_id = t.review_id and topic_id <= t.topic_id and id < t.id
) <= 4
order by t.review_id, t.topic_id
See the demo.
For MySql 8.0+:
with cte as (
select
t.topic_id, t.review_id,
row_number() over (partition by t.review_id order by t.topic_id, t.id) rn
from (
select min(id) id, topic_id, review_id
from topic_id_review_id
group by topic_id, review_id
) t
)
select
c.topic_id, c.review_id
from cte c
where c.rn <= 4
order by c.review_id, c.topic_id
See the demo.
Results:
| topic_id | review_id |
| -------- | --------- |
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 3 | 2 |
| 5 | 2 |
| 2 | 3 |
| 3 | 3 |
| 5 | 4 |
| 6 | 5 |
| 7 | 7 |
Related
Today I have posted a question and got a good answer: Stuck in building mysql query.
I though it helped me, but I've discovered that it returns wrong data. So I'm reposting the question here, with an answer I received, as well I will explain the problem why it is not working for me.
Example of data:
id | item_id | user_id | bid_price
----------------------------------
1 | 1 | 11 | 1
2 | 1 | 12 | 2
3 | 1 | 13 | 3
4 | 1 | 14 | 1
5 | 1 | 15 | 4
6 | 2 | 16 | 2
7 | 2 | 17 | 1
8 | 3 | 18 | 2
9 | 3 | 19 | 3
10 | 3 | 18 | 2
Expected result:
id | item_id | user_id | bid_price
----------------------------------
1 | 1 | 11 | 1
7 | 2 | 17 | 1
8 | 3 | 18 | 2
Offered solution:
select m.id, m.item_id, m.user_id, m.bid_price
from my_table m
inner join (
select item_id, min(id) min_id, min(bid_price) min_price
from my_table
where item_id IN (1,2,3)
group by item_id
) t on t.item_id = m.item_id
and t.min_price= m.bid_price
and t.min_id = m.id
The problem:
In the sub query the minimum ID is selected entire the group by (item_id) statement and doesn't reflects according to minimum bid_price.
In other words, the minimum id is selected not depending on the price field at all. So, in the result I will get minimum price and minimum id of the group, but this will not be the same row! The id can be related to the row with another bet_price value.
How this query can be adjusted? Thank you in advance!
SELECT min(m.id) AS id, m.item_id, m.user_id, m.bid_price
FROM my_table m
INNER JOIN (
SELECT item_id, min(bid_price) AS min_price
FROM my_table
GROUP BY item_id
) t ON t.item_id = m.item_id
AND t.min_price= m.bid_price
GROUP BY item_id
Output
id item_id user_id bid_price
1 1 11 1
7 2 17 1
8 3 18 2
Live Demo
http://sqlfiddle.com/#!9/a52dc6/13
SELECT DISTINCT
t1.item_id,
t1.bid_price
FROM tab1 t1
WHERE NOT exists(SELECT 1
FROM tab1 t2
WHERE t2.item_id = t1.item_id
AND t2.bid_price < t1.bid_price)
AND t1.item_id IN (1, 2, 3);
http://sqlfiddle.com/#!9/615e0a/5
I have this table:
+--------+------+----------+
| fromId | toId | messages |
+--------+------+----------+
| 10 | 2 | 'text' |
| 10 | 4 | 'text' |
| 4 | 10 | 'text' |
| 5 | 10 | 'text' |
| 5 | 10 | 'text' |
| 10 | 3 | 'text' |
| 6 | 10 | 'text' |
+--------+------+----------+
Every row is a message from fromId to toId.
As you can see I have 5 conversations in which user whose ID is 10 is involved:
10 with 2
10 with 4
10 with 5
10 with 3
10 with 6
How can I count them in a Select query??
I have tried this one:
SELECT * FROM messaggi WHERE fromId = 10 OR toID = 10 GROUP BY (fromId)
but something tells me that I have to try a SELECT from another SELECT, I think it's called a subquery.
The answer is equal to the number of rows returned by this query:
SELECT DISTINCT from_id x FROM my_table WHERE to_id = 10
UNION
SELECT DISTINCT to_id x FROM my_table WHERE from_id = 10;
If I understand 10, 5 is the same as 5, 10 so doesnt matter who start the conversation, so:
SQL DEMO
SELECT COUNT(*)
FROM (SELECT DISTINCT
LEAST(`fromId`, `toId`) AS a,
GREATEST(`fromId`, `toId`) AS b
FROM Table1
WHERE 10 in (`fromId`, `toId`)
) T
So we need to find the total number of distinct conversations in any direction. What we can do is query the results and union them together but switch the columns around for one of the queries. This gives us all results for conversations in any direction. We then can count the distinct results to find out how many conversations there are for an individual.
SELECT COUNT(DISTINCT *) FROM
(SELECT fromId as col1, toId as col2 FROM conversations WHERE fromId = 10
UNION
SELECT toId as col1, fromId as col2 FROM conversations WHERE toId = 10)
I would suggest you to change the way it is constructed. Have one table for threads:
TID
---
1
2
3
4
5
6
7
And now, each thread can have any (right now 2) number of participants. So, let's have participants table.
TID | UID
----+----
1 | 10
1 | 2
2 | 10
2 | 4
3 | 4
3 | 10
4 | 5
4 | 10
5 | 5
5 | 10
6 | 10
6 | 3
7 | 6
7 | 10
Now, if you find the count of the participated ones, in a distinct way:
SELECT DISTINCT(GROUP_CONCAT(`UID` ORDER BY `UID` ASC)) FROM participants GROUP BY `TID`
You get this:
And finally, wrapping it with COUNT gives you 5:
SELECT COUNT(*) FROM (SELECT DISTINCT(GROUP_CONCAT(`UID` ORDER BY `UID` ASC)) FROM `participants` GROUP BY `TID`) AS T
I have a forum and I would like to find the most popular users. The most popular users definded by the most likes on posts and comments and also defined by the most total posts and comments. A user with the most likes (order 1), most posts (order 2) and most comments (order 3) is the most popular. Same logic applies for the next (second) most popular user.
So I have 3 tables:
posts table
id user_id likes
1 1 0
2 1 0
3 1 0
4 1 0
5 1 0
6 1 1
7 1 0
8 2 0
9 2 2
10 2 0
11 2 0
12 3 0
13 3 0
14 4 0
15 4 10
comments table
id user_id likes
1 1 0
2 1 1
3 1 1
4 1 0
5 2 0
6 2 2
7 2 1
8 4 1
9 4 0
users table
id name
1 John
2 Adam
3 Maggie
4 Steve
The likes column contains the likes given by other users on the respective post (row).
I tried:
SELECT DISTINCT c.id, c.name,
SUM(a.likes), SUM(b.likes), (SUM(a.likes) + SUM(b.likes)) as popular,
COUNT(a.id) as mostp, COUNT(b.id) as mostc
FROM posts as a, comments as b, users as c
WHERE a.user_id=b.user_id AND a.user_id=c.id AND b.user_id=c.id
GROUP BY a.user_id, b.user_id ORDER BY popular DESC, mostp DESC, mostc DESC
Obviously, this does not work, because if you test the query it gives more likes(sum) than expected.
Here is the live query
http://sqlfiddle.com/#!2/08900/3
The problem with your query is with users that have more than one post and more than one comment, resulting in a cartesian product and producing the wrong sums.
The query below (example on SQL Fiddle) should work, since the subqueries already group by user_id:
SELECT
u.name,
COALESCE(p.likes,0) + COALESCE(c.likes,0) AS likes,
COALESCE(p.cnt,0) AS post_count,
COALESCE(c.cnt,0) AS comment_count
FROM users u
LEFT JOIN (
SELECT user_id, COUNT(1) AS cnt, SUM(likes) AS likes
FROM posts
GROUP BY user_id
) p ON ( p.user_id = u.id )
LEFT JOIN (
SELECT user_id, COUNT(1) AS cnt, SUM(likes) AS likes
FROM comments
GROUP BY user_id
) c ON ( c.user_id = u.id )
ORDER BY likes DESC, post_count DESC, comment_count DESC;
Result:
| NAME | LIKES | POST_COUNT | COMMENT_COUNT |
-----------------------------------------------
| Steve | 11 | 2 | 2 |
| Adam | 5 | 4 | 3 |
| John | 3 | 7 | 4 |
| Maggie | 0 | 2 | 0 |
Here is how you can do this
SELECT
u.id,
u.name,
(l.likes + r.likes) As TotalLikes,
IFNULL(posts,0) AS TotalPosts,
IFNULL(comments,0) AS TotalComments
FROM users AS u
LEFT JOIN (SELECT
user_id,
IFNULL(SUM(likes),0) as likes,
COUNT(likes) as posts
FROM posts
GROUP BY user_id) AS l
on l.user_id = u.id
LEFT JOIN (SELECT
user_id,
IFNULL(SUM(likes),0) as likes,
COUNT(likes) AS comments
FROM comments
GROUP BY user_id) AS r
on r.user_id = u.id
ORDER BY TotalLikes DESc
SQL Fiddle Demo
Output
| ID | NAME | TOTALLIKES | TOTALPOSTS | TOTALCOMMENTS |
---------------------------------------------------------
| 4 | Steve | 11 | 2 | 2 |
| 2 | Adam | 5 | 4 | 3 |
| 1 | John | 3 | 7 | 4 |
| 3 | Maggie | 0 | 2 | 0 |
i have a scenario, lets say 3 users review a business of id 10, how can i get all the unique id of the user who review that business and and use that unique id to find another business review which is not equal to 10 ?
sample table user_review:
review_id | user_id | business_id | rating | review_date
1 2 10 3 20121030124001
2 2 9 3 20121022120627
3 2 10 4 20121023120627
4 3 10 4 20121024120627
5 3 6 3 20121022140627
6 4 10 2 20121025120627
7 4 10 5 20121030120627
8 3 10 2 20121010120627
9 4 8 5 20121028120627
i should get result of these
review_id | user_id | business_id | rating | review_date
2 2 9 3 20121022120627
5 3 6 3 20121022140627
9 4 8 5 20121028120627
In a above result if there is 2 reviews for a same user_id and same business_id the latest one should be return.Thanks
Try this query:
Here is link to sqlfidle with running results http://sqlfiddle.com/#!2/cd4ea/1
SELECT
tblreview.*,tblusers.user_name
FROM
(
SELECT
MAX(tblreview.review_id) review_id
, tblreview.user_id
FROM
(
SELECT
DISTINCT user_id
FROM
tblreview
WHERE business_id = 10
) reviewsb10
INNER JOIN
tblreview
ON
tblreview.user_id = reviewsb10.user_id
AND
tblreview.business_id <> 10
GROUP BY
user_id
) tblLastReviewPerUser
INNER JOIN
tblreview
ON
tblreview.review_id = tblLastReviewPerUser.review_id
INNER JOIN
tblusers
ON
tblusers.user_id = tblLastReviewPerUser.user_id
SELECT t1.*
FROM TableName t1
INNER JOIN
(
SELECT user_id, business_id, MAX(review_date) review_date
FROM TableName
WHERE business_id <> 10
GROUP BY user_id, business_id
) t2 ON t1.user_id = t2.user_id
AND t1.review_date = t2.review_date
AND t1.business_id = t2.business_id
Try this query -
SELECT * FROM (
SELECT * FROM user_review
ORDER BY IF(business_id = 10, 1, 0), review_date DESC
) t
GROUP BY user_id
HAVING
COUNT(IF(business_id = 10, 1, NULL)) > 0
AND COUNT(IF(business_id <> 10, 1, NULL)) > 0
+-----------+---------+-------------+--------+----------------+
| review_id | user_id | business_id | rating | review_date |
+-----------+---------+-------------+--------+----------------+
| 2 | 2 | 9 | 3 | 20121022120627 |
| 5 | 3 | 6 | 3 | 20121022140627 |
| 9 | 4 | 8 | 5 | 20121028120627 |
+-----------+---------+-------------+--------+----------------+
I have X Categories, Y Forums and Z threads.
Threads belong to one Forum
Forums belong to one Category
I want to be able to select X Categories and
to each Category select the first 3 Forums and
to each Forum select the first 4 Threads.
(numbers only as an example)
I did this by emulating row_numbers via variables, as mysql does not support this out of the box.
Unfotunately there is still something wrong with the row-numbers. Maybe someone could have a look what is wrong here.
For better readability I have uploaded the query and results here with code-highlighting
SELECT
CatRow,
c_id,
c_name,
ForumRow,
f_id,
f_name,
ThreadRow,
t_id,
t_title
FROM (
SELECT
#cat_row := IF(#prev_cat = c.id, #cat_row+1, 1) AS CatRow,
#forum_row := IF(#prev_forum = f.id, #forum_row+1, 1) AS ForumRow,
#thread_row := IF(#prev_thread = t.id, #thread_row+1, 1)AS ThreadRow,
c.id AS c_id,
c.name AS c_name,
f.id AS f_id,
f.name AS f_name,
t.id AS t_id,
t.title AS t_title,
#prev_cat := c.id,
#prev_forum := f.id,
#prev_thread:= t.id
FROM (
SELECT
*
FROM
forum_categories c,
(SELECT #cat_row := 1) AS x,
(SELECT #prev_cat := '') AS y
ORDER BY #cat_row
) AS c
LEFT JOIN (
SELECT
*
FROM
forum_forums AS f,
(SELECT #forum_row := 1) AS x,
(SELECT #prev_forum := '') AS y
ORDER BY #forum_row
) AS f ON (c.id = f.fk_forum_category_id )
LEFT JOIN (
SELECT
*
FROM
forum_threads AS t,
(SELECT #thread_row := 1) AS x,
(SELECT #prev_thread := '') As y
ORDER BY #thread_row
) AS t ON (f.id = t.fk_forum_forums_id )
ORDER BY c.id ASC, f.id ASC, t.id ASC
) c
-- This is for later to actually limit the joins
-- WHERE CatRow <= 3 AND
-- ForumRow <= 3 AND
-- ThreadRow <= 4
The results look as follows:
CatRow c_id c_name ForumRow f_id f_name ThreadRow t_id t_title
4 1 General 4 2 Talk 1 42 talk
5 1 General 5 2 Talk 1 43 Talk...
6 1 General 6 2 Talk 1 44 locked thread
7 1 General 7 2 Talk 1 45 closed thread
3 1 General 3 2 Talk 1 48 :(:red::confuse::)
1 1 General 1 2 Talk 1 50 gsfdgsdg
2 1 General 2 2 Talk 1 51 asdasd
9 1 General 2 5 Voting 1 47 some title
8 1 General 1 5 Voting 1 49 sadfsad
1 2 Support 1 3 Help 1 40 Hueeelefe
2 2 Support 1 4 Features and Bugs 1 41 What is a bug?
3 2 Support 1 7 Test 1 NULL NULL
2 3 News 2 1 News 1 39 News by admin
1 3 News 1 1 News 1 46 further news
At the end I need to be able to specify:
WHERE CatRow <= 9 AND
ForumRow <= 3
AND ThreadRow <= 4
This is not yet possible due to the wrong row_numbers.
Any ideas???
Actually I want the results to look like this:
CatRow c_id c_name ForumRow f_id f_name ThreadRow t_id t_title
1 1 General 1 2 Talk 1 42 talk
1 1 General 1 2 Talk 2 43 Talk...
1 1 General 1 2 Talk 3 44 locked thread
1 1 General 1 2 Talk 4 45 closed thread
1 1 General 1 2 Talk 5 48 :(:red::confuse::)
1 1 General 1 2 Talk 6 50 gsfdgsdg
1 1 General 1 2 Talk 7 51 asdasd
1 1 General 2 5 Voting 1 47 some title
1 1 General 2 5 Voting 2 49 sadfsad
2 2 Support 1 3 Help 1 40 Hueeelefe
2 2 Support 2 4 Features and Bugs 1 41 What is a bug?
2 2 Support 3 7 Test 1 NULL NULL
3 3 News 1 1 News 1 39 News by admin
3 3 News 1 1 News 2 46 further news
For better readability I have uploaded the pictures of query and results with code-highlighting:
http://i.stack.imgur.com/9tzmH.png
http://i.stack.imgur.com/xXF6U.png
SQL Fiddle
set #c_row := 0, #f_row := 0, #t_row := 0;
set #cat := 0, #forum := 0;
select CatRow, c_id, c_name, ForumRow, f_id, f_name, ThreadRow, t_id, title
from (
select
#c_row := if(#cat = c_id, #c_row, #c_row + 1) CatRow,
#f_row := if(#forum = f_id, #f_row, if(#cat = c_id, #f_row + 1, 1)) ForumRow,
#t_row := if(#forum = f_id, #t_row + 1, 1) ThreadRow,
#cat := c_id as a,
#forum := f_id as b,
c_id,
c_name,
f_id,
f_name,
t_id,
title
from (
select
c.id c_id, f.id f_id, t.id t_id,
c.name c_name, f.name f_name, title
from
forum_categories c
inner join
forum_forums f on f.c_id = c.id
inner join
forum_threads t on t.f_id = f.id
order by
c.id, f.id, t.id
) s
) s;
+--------+------+---------+----------+------+-------------------+-----------+------+--------------------+
| CatRow | c_id | c_name | ForumRow | f_id | f_name | ThreadRow | t_id | title |
+--------+------+---------+----------+------+-------------------+-----------+------+--------------------+
| 1 | 1 | General | 1 | 2 | Talk | 1 | 42 | talk |
| 1 | 1 | General | 1 | 2 | Talk | 2 | 43 | Talk... |
| 1 | 1 | General | 1 | 2 | Talk | 3 | 44 | locked thread |
| 1 | 1 | General | 1 | 2 | Talk | 4 | 45 | closed thread |
| 1 | 1 | General | 1 | 2 | Talk | 5 | 48 | :(:red::confuse::) |
| 1 | 1 | General | 1 | 2 | Talk | 6 | 50 | gsfdgsdg |
| 1 | 1 | General | 1 | 2 | Talk | 7 | 51 | asdasd |
| 1 | 1 | General | 2 | 5 | Voting | 1 | 47 | some title |
| 1 | 1 | General | 2 | 5 | Voting | 2 | 49 | sadfsad |
| 2 | 2 | Support | 1 | 3 | Help | 1 | 40 | Hueeelefe |
| 2 | 2 | Support | 2 | 4 | Features and Bugs | 1 | 41 | What is a bug? |
| 3 | 3 | News | 1 | 1 | News | 1 | 39 | News by admin |
| 3 | 3 | News | 1 | 1 | News | 2 | 46 | further news |
+--------+------+---------+----------+------+-------------------+-----------+------+--------------------+
I have solved it by now:
This works on all levels. I added posts per thread as well
SELECT
CatRow,
c_id,
c_name,
ForumRow,
f_id,
f_name,
ThreadRow,
t_id,
t_title,
PostRow,
p_id,
p_title
FROM (
SELECT
#cat_row := IF(#prev_cat = c.id, #cat_row, #cat_row+1) AS CatRow,
#forum_row := IF(#prev_forum = f.id, #forum_row, IF(#prev_cat = c.id, #forum_row+1, 1)) AS ForumRow,
#thread_row := IF(#prev_thread = t.id, #thread_row, IF(#prev_forum = f.id, #thread_row+1, 1))AS ThreadRow,
#post_row := IF(#prev_post = t.id, #post_row, IF(#prev_thread= t.id, #post_row+1, 1)) AS PostRow,
c.id AS c_id,
c.name AS c_name,
f.id AS f_id,
f.name AS f_name,
t.id AS t_id,
t.title AS t_title,
p.id AS p_id,
p.title AS p_title,
#prev_cat := c.id,
#prev_forum := f.id,
#prev_thread:= t.id,
#prev_post := p.id
FROM (
SELECT
*
FROM
forum_categories,
(SELECT #cat_row := 0) AS x,
(SELECT #prev_cat := '') AS y
ORDER BY YOUR_ORDER_HERE
) AS c
LEFT JOIN (
SELECT
*
FROM
forum_forums,
(SELECT #forum_row := 0) AS x,
(SELECT #prev_forum := '') AS y
ORDER BY YOUR_ORDER_HERE
) AS f ON (c.id = f.fk_forum_category_id )
LEFT JOIN (
SELECT
*
FROM
forum_threads,
(SELECT #thread_row := 0) AS x,
(SELECT #prev_thread := '') As y
ORDER BY YOUR_ORDER_HERE
) AS t ON (f.id = t.fk_forum_forums_id )
LEFT JOIN (
SELECT
*
FROM
forum_posts AS p,
(SELECT #post_row := 0) AS x,
(SELECT #prev_post := '') As y
ORDER BY YOUR_ORDER_HERE
) AS p ON (t.id = p.fk_forum_thread_id )
) c
-- WHERE CatRow <= HOW_MANY_CATS AND ForumRow <= HOW_MANY_FORUMS_PER_CAT AND ThreadRow <= HOW_MANY_THREADS_PER_FORUM AND PostRow <= HOW_MANY_POSTS_PER_THREAD
CatRow c_id c_name ForumRow f_id f_name ThreadRow t_id t_title PostRow p_id p_title
1 1 General 1 2 Talk 1 50 gsfdgsdg 1 NULL NULL
1 1 General 1 2 Talk 2 51 asdasd 1 NULL NULL
1 1 General 1 2 Talk 3 48 :(:red::confuse::) 1 80 t1
1 1 General 1 2 Talk 3 48 :(:red::confuse::) 2 79 NULL
1 1 General 1 2 Talk 3 48 :(:red::confuse::) 3 78 NULL
1 1 General 1 2 Talk 4 42 talk 1 76 NULL
1 1 General 1 2 Talk 4 42 talk 2 75 sdfg
1 1 General 1 2 Talk 4 42 talk 3 74 NULL
1 1 General 1 2 Talk 4 42 talk 4 73 NULL
1 1 General 1 2 Talk 4 42 talk 5 72 NULL
1 1 General 1 2 Talk 5 43 Talk... 1 NULL NULL
1 1 General 1 2 Talk 6 44 locked thread 1 NULL NULL
1 1 General 1 2 Talk 7 45 closed thread 1 NULL NULL
1 1 General 2 5 Voting 1 49 sadfsad 1 77 NULL
1 1 General 2 5 Voting 2 47 some title 1 NULL NULL
2 3 News 1 1 News 1 46 further news 1 NULL NULL
2 3 News 1 1 News 2 39 News by admin 1 71 NULL
2 3 News 1 1 News 2 39 News by admin 2 68 NULL
2 3 News 1 1 News 2 39 News by admin 3 67 NULL
3 2 Support 1 3 Help 1 40 Hueeelefe 1 70 NULL
3 2 Support 1 3 Help 1 40 Hueeelefe 2 69 NULL
3 2 Support 2 4 Features and Bugs 1 41 What is a bug? 1 NULL NULL
3 2 Support 3 7 Test 1 NULL NULL 1 NULL NULL
Using dependent subqueries with LIMIT may solve your problem:
SELECT CatRow, c_id, c_name, ForumRow, f_id, f_name, ThreadRow, t_id, t_title
FROM forum_categories c
INNER JOIN (SELECT * FROM forum_forums f WHERE f.fk_forum_category_id=c.id LIMIT 3) AS t1
INNER JOIN (SELECT * FROM forum_threads t WHERE t.fk_forum_forums_id=f.id LIMIT 4) AS t2