如何根据多个不同的组计算行数?

时间:2016-07-02 14:58:45

标签: mysql sql

这是我的表结构:

// 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

我正在尝试实现此(与stackoverflow完全相同的东西)。用户可以询问:

  • 每90分钟1个问题
  • 每天6个问题
  • 每月50个问题

因此,在让他询问之前,我需要为用户计算上一个问题的数量。我怎么能这样做?

这是我的问题:

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 */

2 个答案:

答案 0 :(得分:1)

可能是某些事情可以解决这个问题

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  ) 

小心不要..check也是空的结果..

答案 1 :(得分:0)

@ scaisEdge解决方案的简化会删除子查询中的聚合,使用标量比较,并且不会在外部查询中引用QandA

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;

更高效的版本只进行一次聚合:

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;

我也认为这更容易阅读。