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
Related
This is a follow-up question to How to show rows in packs of three in MySQL
I have two tables:
mytable
ID Type Timestamp
1 A 101
2 A 102
3 B 103
4 B 104
5 A 105
6 B 106
7 A 107
8 A 108
9 B 109
10 A 110
11 B 111
12 B 112
mytable 2
ID2 Text Status
1 x 1
2 x 1
3 y 1
4 y 1
5 x 1
6 y 1
7 x 1
8 x 1
9 y 1
10 x 0
11 y 1
12 y 0
I want to show a result sorted by Type and Timestamp where every 3 rows the Type changes like this (rows with Status=0 are skipped):
ID Type Timestamp Text
1 A 101 x
2 A 102 x
5 A 105 x
3 B 103 y
4 B 104 y
6 B 106 y
7 A 107 x
8 A 108 x
9 B 109 y
11 B 111 y
I tried this:
SELECT id, type, timestamp, text
FROM (
SELECT
t.*,t2.text,t2.id2,
#rn := CASE WHEN #type = type THEN #rn + 1 ELSE 1 END rn,
#type := type
FROM
mytable t, mytable2 t2
WHERE t2.id2=t.id
AND status=1
CROSS JOIN (SELECT #type := NULL, #rn := 1) x
ORDER BY type, timestamp
) x
ORDER BY
FLOOR((rn - 1)/3),
type,
timestamp;
[Demo on DB Fiddle] (https://www.db-fiddle.com/f/7urWNPqXyGQ5ANVqxkjD7q/1)
To start with, yo would just need to fix your JOIN, whose syntax is not correct (typically, the WHERE clause goes after all JOINs, and we prefer explicit joins over implicit joins).
Also, as commented by Madhur Bhaiya, using filters with incremented variables is tricky. For this to work properly, we would need to join the two tables in a subquery, and do the ordering inside the subquery itself, and then proceed with the variable logic.
Consider:
SELECT id, type, timestamp, text
FROM (
SELECT
t.*,
#rn := CASE WHEN #type = type THEN #rn + 1 ELSE 1 END rn,
#type := type
FROM
(
SELECT t.*, t2.text,t2.id2
FROM mytable t
INNER JOIN mytable2 t2 ON t2.id2=t.id AND status=1
ORDER BY type, timestamp
) t
CROSS JOIN (SELECT #type := NULL, #rn := 1) x
) x
ORDER BY FLOOR((rn - 1)/3), type, timestamp;
Demo on DB Fiddle:
| id | type | timestamp | text |
| --- | ---- | --------- | ---- |
| 1 | A | 101 | x |
| 2 | A | 102 | x |
| 5 | A | 105 | x |
| 3 | B | 103 | y |
| 4 | B | 104 | y |
| 6 | B | 106 | y |
| 7 | A | 107 | x |
| 8 | A | 108 | x |
| 9 | B | 109 | y |
| 11 | B | 111 | y |
I have the following table:
ID | team1 | team2 | Date
-----------------------------
1 | 36 | 25 | 2019-01-05
2 | 25 | 39 | 2019-01-07
3 | 36 | 39 | 2019-01-09
4 | 36 | 11 | 2019-01-10
5 | 11 | 25 | 2019-01-11
6 | 25 | 36 | 2019-01-12
How to get last 2 entries for team 25 and 36. Good result is:
ID | team1 | team2 | Date
-----------------------------
4 | 36 | 11 | 2019-01-10 > 36
5 | 11 | 25 | 2019-01-11 > 25
6 | 25 | 36 | 2019-01-12 > 25 & 36
25 and 36 is just for example. We can have a long list of teams, as well as a very large list of entries. If the search would be carried out on one column, for example team1 then the query would look like this:
SELECT * FROM (
SELECT
ID, team1, team2, `Date`,
CASE WHEN #id != team1 THEN #rownum := 1 ELSE #rownum := #rownum + 1 END AS rank,
#id := team1
FROM matches
JOIN (SELECT #rownum := 0, #id := NULL) r
WHERE team1 IN(25, 36)
OREDER BY team1, `Date` DESC
) WHERE rank <= 2
You can use a LEFT OUTER JOIN to join the table against itself for later games, and discard any rows where there is a layter game:-
SELECT a.*
FROM matches a
LEFT OUTER JOIN matches b
ON a.team1 = b.team1
AND a.`date` < b.`date`
WHERE b.id IS NULL
AND a.team1 IN (25, 36)
If you apply your query to the UNION of the 2 columns and join to the table you will get the result that you want:
SELECT DISTINCT m.*
FROM matches m INNER JOIN (
SELECT * FROM (
SELECT team, `Date`,
CASE WHEN #id != team THEN #rownum := 1 ELSE #rownum := #rownum + 1 END AS rank,
#id := team
FROM (
SELECT team1 team, date FROM matches
UNION ALL
SELECT team2, date FROM matches
) t
JOIN (SELECT #rownum := 0, #id := NULL) r
WHERE team IN (25, 36)
ORDER BY team, `Date` DESC
) t
WHERE rank <= 2
) t ON t.`Date` = m.`Date` AND t.team IN (m.team1, m.team2)
See the demo.
Results:
| ID | team1 | team2 | Date |
| --- | ----- | ----- | ------------------- |
| 4 | 36 | 11 | 2019-01-10 00:00:00 |
| 5 | 11 | 25 | 2019-01-11 00:00:00 |
| 6 | 25 | 36 | 2019-01-12 00:00:00 |
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 |
This is example of my table :
+-----+-----+------------+--------+-------------+--------------+
| LID | AID | Created | TypeID | PaymentDate | PaymentValue |
+-----+-----+------------+--------+-------------+--------------+
| 1 | 529 | 2017-05-12 | 1 | 2017-05-12 | 100 |
+-----+-----+------------+--------+-------------+--------------+
| 2 | 529 | 2018-04-10 | 4 | 2018-04-10 | 200 |
+-----+-----+------------+--------+-------------+--------------+
| 3 | 441 | 2014-01-23 | 3 | 2014-01-23 | 300 |
+-----+-----+------------+--------+-------------+--------------+
| 4 | 324 | 2017-09-14 | 1 | 2017-09-14 | 400 |
+-----+-----+------------+--------+-------------+--------------+
| 5 | 111 | 2018-05-12 | 0 | 2018-05-12 | 340 |
+-----+-----+------------+--------+-------------+--------------+
| 6 | 529 | 2018-05-12 | 1 | 2018-05-12 | 100 |
+-----+-----+------------+--------+-------------+--------------+
| 7 | 529 | 2018-06-12 | 1 | 2018-05-12 | 100 |
+-----+-----+------------+--------+-------------+--------------+
| 8 | 529 | 2018-07-12 | 1 | 2018-05-12 | 100 |
+-----+-----+------------+--------+-------------+--------------+
| 9 | 529 | 2018-08-12 | 1 | 2018-05-12 | 100 |
+-----+-----+------------+--------+-------------+--------------+
| 10 | 529 | 2018-09-12 | 1 | 2018-05-12 | 100 |
+-----+-----+------------+--------+-------------+--------------+
| 11 | 529 | 2018-01-12 | 1 | 2018-05-12 | 100 |
+-----+-----+------------+--------+-------------+--------------+
| 12 | 529 | 2018-05-14 | 1 | 2018-05-12 | 100 |
+-----+-----+------------+--------+-------------+--------------+
| 13 | 529 | 2018-05-21 | 1 | 2018-05-12 | 100 |
+-----+-----+------------+--------+-------------+--------------+
| 14 | 529 | 2018-03-12 | 1 | 2018-05-12 | 100 |
+-----+-----+------------+--------+-------------+--------------+
Here another table
+-----+-------+
| ID |caption|
+-----+-------+
| 0 | bad |
+-----+-------+
| 1 | good |
+-----+-------+
I need to get 10 latest records per AID. If there less than 10 records for some AID anyway i need to get ten rows and put "No payment date" into PaymentDate and Created fields, Null into TypeID and 0 into PaymentValue. I can get 10 or less latest records with
select *
from (select *,
(#rn := if(#c = AID, #rn + 1,
if(#c := AID, 1, 1)
)
) as rn
from history cross join
(select #rn := 0, #c := -1) params
order by AID, Created desc
) t
having rn <= 10;
But i dont know how force mysql to output 10 rows for each AID. Help me please.
Result should be in a form
AID,TypeId,Created,Caption
I have done it.
This query needs to create a row of 10 records to combine with distinct AID valies in the table. I was able to show the result for Amount and Create date and will leave it to you to continue since you will get the idea.
The critical part is to build a table with 10 rows times distinct AID so about 40 rows in table r. Then do a left join to table t which is similar to what you have done. Table t gets a rank of at most 10 records. Any missing rank up to 10 recs will be filled by table r. Coalesce will assign the default values such as 0 fro amount and 'no create date' for date.
http://sqlfiddle.com/#!9/855c21/2
SELECT coalesce(r.aid, t.aid) as aid,
coalesce(t.paymentvalue, 0) as paymentvalue,
coalesce(cast(t.created as char), 'no create date') as created
FROM (select * from (
select 1 as rw union
select 2 union select 3
union select 4 union select 5
union select 6 union select 7
union select 8 union select 9
union select 10) u
cross join (select distinct aid
from history) h
) as r
LEFT JOIN (
SELECT a.aid, a.paymentvalue,
a.created, count(*) rn
FROM history a
JOIN history b
ON a.aid = b.aid
AND a.created <= b.created
GROUP BY a.aid, a.created
HAVING COUNT(*) <= 10) t
on r.rw=t.rn and r.aid=t.aid
order by aid, created;
I have added RIGHT JOIN to bring in the null rows to top up to 10 (or n) rows per AID. Initially I use SELECT 1 UNION SELECT 2 ... to generate the 10 rows. In order to make it easier to increase the number of rows (say 100), I am trying this idea of generate_series equivalent for mysql. In order for this to work, the number of rows in history table must be equal to greater than the number of rows required per AID.
select t1.lid
,t2.aid
,coalesce(t1.created, "no created date") as created
,t1.typeID
,coalesce(t1.paymentdate, "no payment date") as paymentDate
,coalesce(t1.paymentvalue, 0) as paymentValue
,t2.rn
from
(
select *,
(#rn := if(#c = AID, #rn + 1,
if(#c := AID, 1, 1)
)
) as rn
from history cross join
(select #rn := 0, #c := -1) params
order by AID, Created desc
) t1
right join
( select *
from (select distinct aid from history ) h1
cross join
(select rn -- generate table with n rows numbered from 1 to n
from
(select
#num:= 0) init
cross join
(select #num := #num +1 rn
from history ) t -- assume history has at least 10 rows
limit
10 ) h2 -- n = 10; change it to the number of rows per aid required
) t2
on t1.aid = t2.aid and t1.rn = t2.rn
order by t2.aid, t2.rn
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 |
+-----------+---------+-------------+--------+----------------+