Reputation: 10218
Here is my table structure:
// QandA
+----+----------------------------------------+------+---------+-----------+------------+
| Id | body | type | related | author_id | date_time |
+----+----------------------------------------+------+---------+-----------+------------+
| 1 | content of question1 | 0 | null | 12345 | 1467468795 |
| 2 | content of first answer for question1 | 1 | 1 | 53456 | 1467469311 |
| 3 | content of question2 | 0 | null | 43634 | 1467469512 |
| 4 | content of second answer for question1 | 1 | 1 | 43665 | 1467470098 |
| 5 | content of first answer for question2 | 1 | 3 | 43324 | 1467471291 |
+----+----------------------------------------+------+---------+-----------+------------+
-- type: 0 means question, 1 means answer
-- related: null means question, else it's the id of its own question
I'm trying to implement this (something exactly like what stackoverflow does). An user can ask:
So I need to count the number of previous question for an user before letting him to ask. How can I do that?
Here is my query:
INSERT INTO QandA (id, body, type, related, author_id, date_tiem)
SELECT NULL, :body, 0, NULL, :id, unix_timestamp
FROM QANDA
WHERE author_id = :id AND
type = 0 AND
/* those three conditions */
Upvotes: 0
Views: 71
Reputation: 1269503
A simplification of @scaisEdge's solution removes the aggregation in the subqueries, uses scalar comparisons, and doesn't reference QandA
in the outer query:
INSERT INTO QandA (id, body, type, related, author_id, date_time)
SELECT NULL, :body, 0, NULL, :id, unix_timestamp
FROM dual
WHERE (select count(*)
from QANDA
where date_time < unix_timestamp(DATE_SUB(now(), INTERVAL 90 minute)) and
author_id = :id and
type >= 1
) < 1
(select count(*)
from QANDA
where date_time < unix_timestamp(DATE_SUB(now(), INTERVAL 1 day)) and
author_id = :id and
type >= 1
) < 6
author_id = :id AND type = 1 AND
(select count(*)
from QANDA
where date_time < unix_timestamp(DATE_SUB(now(), INTERVAL 1 month )) and
author_id = :id and
type >= 1
) < 50;
A more efficient version only does the aggregation once:
INSERT INTO QandA (id, body, type, related, author_id, date_time)
SELECT NULL, :body, 0, NULL, :id, unix_timestamp
FROM (select count(*) as num_month,
coalesce(sum(date_time < unix_timestamp(DATE_SUB(now(), INTERVAL 1 day)), 0) as num_day,
coalesce(sum(date_time < unix_timestamp(DATE_SUB(now(), INTERVAL 90 minute)), 0) as num_90min
from QANDA
where date_time < unix_timestamp(DATE_SUB(now(), INTERVAL 1 month)) and
author_id = :id and
type >= 1
) a
WHERE num_month < 50 and num_day < 6 and num_90min < 1;
I also think this is easier to read.
Upvotes: 0
Reputation: 133360
Could be somethings lke this query
INSERT INTO QandA (id, body, type, related, author_id, date_tiem)
SELECT NULL, :body, 0, NULL, :id, unix_timestamp
FROM QANDA as a
WHERE author_id = :id
AND type = 1
AND a.author_id not in ( select author_id = :id
from QANDA
where date_time < unix_timestamp(DATE_SUB(now(),INTERVAL 90 minute ))
and author_id = :id
and type =>1
group by author_id
having count(*) => 1 )
AND a.author_id not in ( select author_id = :id
from QANDA
where date_time < unix_timestamp(DATE_SUB(now(),INTERVAL 1 DAY ))
and author_id = :id
and type = 1
group by author_id
having count(*) => 6 )
AND a.author_id not in ( select author_id = :id, count(*)
from QANDA
where date_time < unix_timestamp(DATE_SUB(now(),INTERVAL 1 MONTH ))
and author_id = :id
and type = 1
group by author_id
having count(*) => 50 )
Be careful with not in ..check also for empty result ..
Upvotes: 1