1

I have 2 tables:

user          messages
+---------+   +----------------+
|id|credit|   |id|user_id| ... |
+---------+   +----------------+
|01| 05   |   |01| 01    | ... |
|02| 01   |   |02| 01    | ... |
|03| 00   |   |03| 01    | ... |
+---------+   |04| 02    | ... |
              |05| 02    | ... |
              |06| 03    | ... |
              +----------------+

I need to select n messages from messages where n=user.credit. The query I would like to execute a query like:

SELECT * 
FROM user u JOIN messages m ON u.id = m.user_id LIMIT u.credit 
WHERE user in ...;

And should return rows 01, 02, 03, 04 but not 05, 06.

I know I can't write LIMIT u.credit but want that behavior, limit the number of messages fetched for each user in function of the value of the credits they have (user 01 whit limit of 5, user 02 with limit of 1 and so on) and I want to fetch all the messages all at once to avoid having to do a COUNT and then a SELECT for each user.

I'm using MySQL with InnoDB

4
  • 2
    u.id == m.user_id should be u.id = m.user_id Commented Jan 9, 2013 at 17:42
  • You can only specify a constant literal for LIMIT, not an expression. Commented Jan 9, 2013 at 17:46
  • 2
    Directly in mysql, your best bet is to write a stored procedure that selects the u.credit value into a variable, then builds a query-string using that value as the limit and then having the procedure execute that query. Commented Jan 9, 2013 at 17:48
  • @SalmanA I know, I'm looking for a workaround, but avoiding making multiple queries. Commented Jan 9, 2013 at 17:48

3 Answers 3

4

This is a solution in plain SQL, without using variables:

select user.*, messages.*
from user inner join messages
     on user.id=messages.user_id
where (select count(*) from messages m
       where m.user_id=user.id
       and m.id<messages.id)<user.credit

Demo

Sign up to request clarification or add additional context in comments.

Comments

1

I'm afraid this is going to be slow:

SELECT u.*
     , m.*
FROM 
    user AS u 
  JOIN
    ( SELECT m1.*, COUNT(*) AS cnt
      FROM messages m1
        JOIN messages m2
          ON  m2.user_id = m1.user_id 
          AND m2.id <= m1.id
      GROUP BY m1.user_id, m1.id 
    ) m 
      ON  m.user_id = u.id 
      AND m.cnt <= u.credit ;

Demo

Comments

0

There is a way to do that in SQL if you are determined to.

SELECT u.* 
FROM user u JOIN messages m ON u.id = m.user_id
  inner join user u2 on u2.id <= u.id
WHERE user in ...
GROUP BY u.id
HAVING count(u2.id) < u.credit

2 Comments

It seems good, but MySQL does not allow expressions on the LIMIT clause
I see that it should be <= instead of <. I'll edit my answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.