1

I've been stuck in a complex MySQL query. Here is my table:

+---------------------------------------------------+
| id | user_id | category_id | post_id | view_count |
+---------------------------------------------------+
| 1  | 23      | 5           | 213     | 0          |
| 2  | 23      | 5           | 214     | 0          |
| 3  | 23      | 5           | 215     | 0          |
| 4  | 23      | 5           | 216     | 0          |
| 5  | 23      | 6           | 217     | 0          |
| 6  | 23      | 6           | 218     | 0          |
| 7  | 23      | 6           | 219     | 0          |
| 8  | 23      | 6           | 220     | 0          |
| 9  | 55      | 13          | 221     | 0          |
| 10 | 55      | 13          | 222     | 0          |
| 11 | 55      | 16          | 223     | 0          |
| 12 | 55      | 16          | 234     | 0          |
| 13 | 55      | 22          | 235     | 0          |
| 14 | 55      | 22          | 256     | 0          |
| 15 | 55      | 22          | 261     | 0          |
| 16 | 62      | 13          | 272     | 0          |
| 17 | 62      | 13          | 273     | 0          |
| 18 | 62      | 24          | 277     | 0          |
| 19 | 62      | 24          | 278     | 0          |
| 20 | 62      | 24          | 288     | 0          |
| 21 | 62      | 31          | 289     | 0          |
| 22 | 62      | 31          | 290     | 0          |
+---------------------------------------------------+

Now what I wish is for each user_id I want 3 rows of data but each row should have a different category_id, like the below resultset:

+--------------------------------------+
| id | user_id | category_id | post_id |
+--------------------------------------+
| 1  | 23      | 5           | 213     |
| 5  | 23      | 6           | 217     |
| 9  | 55      | 13          | 221     |
| 11 | 55      | 16          | 223     |
| 16 | 62      | 13          | 272     |
| 18 | 62      | 24          | 277     |
+--------------------------------------+

The query I've used is as follows:

SELECT id,user_id,category_id,post_id,view_count,rank 
FROM ( 
    SELECT tt.* ,@rank:= CASE WHEN @group = user_id THEN @rank + 1 ELSE 1 END rank,@group:= tt.user_id 
    FROM ( 
         SELECT id,user_id,category_id,post_id, view_count 
         FROM product_table 
         WHERE view_count=(SELECT MIN(view_count) FROM product_table
    ) 
    GROUP BY user_id,category_id 
    ORDER BY user_id,category_id 
) tt 
JOIN (SELECT @rank:=0,@group:=0) t1) new_t 
WHERE rank <=3 LIMIT 9

This query was suggested to me by @m-khalid-junaid in my previous question: SELECT 3 records per user group by on two columns And I tweaked that query to incorporate the MIN(view_count) value. What I do now is after the resultset is retrieved I increment the view_count by 1
But this query runs as follows:

if "User 1" has 6 posts in 3 categories, having each category contain 2 posts  
And  
if "User 2" has 9 posts in 3 categories, having each category containing 3 posts  
And  
if "User 3" has 7 posts in 3 categories, having 2 categories containing 2 posts and the last category which has 3 posts  

Then the SQL when running repeatedly uses following cycle:

Cycle 1:  
Show first 3 posts of "User 1" from each of the category [1-3]  
Show first 3 posts of "User 2" from each of the category [1-3]  
Show first 3 posts of "User 3" from each of the category [1-3]  

Cycle 2:  
Show next 3 posts of "User 1" from each of the category [4-6]  
Show next 3 posts of "User 2" from each of the category [4-6]  
Show next 3 posts of "User 3" from each of the category [4-6]  

Cycle 3:  
Show next 3 posts of "User 2" from each of the category [7-9]  
Show remaining 1 post of "User 3" from last category [7]  

What I wish is if no more "User 1" posts are available in "Cycle 3", then fetch the posts used in Cycle 1 for "User 1" And in "Cycle 3" there is only 1 post of "User 3" so in that case I wish that Cycle 3 uses last 1 post and fetches Cycle 1's 2 posts for "User 3". Note that these posts will now be having view_count incremented to 1 in last cycle.

I hope I explained it correctly.

Community
  • 1
  • 1
khalid
  • 367
  • 2
  • 15
  • 1
    can you make a fiddle at http://sqlfiddle.com – Muhammad Raheel Jun 12 '14 at 08:04
  • At a glance it looks like the GROUP BY clause is not required. That will bring back one record for each user id / category (possibly what is require) with an undefined id and post_id (ie, coming from an undefined row). – Kickstart Jun 12 '14 at 08:25
  • Why don't you want ids 13 & 21? And, instead of '3 rows of data', do you mean '**a maximum** of **2** rows of data' ? – Strawberry Jun 12 '14 at 09:58
  • @Strawberry Well, this is just sample data.. What I explained in "Cycles" section is the exact requirements I need. I need there to be batches of products and each batch should contain 3 products of a single user. – khalid Jun 12 '14 at 10:16
  • @raheel Here is the SQLFiddle, http://sqlfiddle.com/#!2/a24cf5/1 – khalid Jun 12 '14 at 10:36

0 Answers0