MySQL子查询计算

时间:2011-11-29 22:03:25

标签: mysql vb.net

我有这个mysql查询,当我搜索用户并且他有一个登录(开始 - 结束)时,它显示下一行的总数,但如果用户有多个登录(开始 - 结束)它不会显示下一行的总数....

SELECT CONCAT(u.lastname, ', ', u.firstname) AS Name
   , start.timestamp start
   , end.timestamp end
   , timediff(end.timestamp, start.timestamp) duration 
FROM user u
   , user_group ug
   , (
      select *
         , (
            select event_id
            from event L2 
            where L2.timestamp > L1.timestamp
               and L2.user_bannerid = L1.user_bannerid
            order by timestamp limit 1  
           ) stop_id
      From event L1
     ) start
join event end on end.event_id = start.stop_id
where start.status = 'In'
   and end.status='Out'
   and u.user_bannerid = start.user_bannerid
   and ug.user_bannerid = u.user_bannerid
   and ug.group_id = start.group_id 

UNION

SELECT null, null, null, CAST(sum(duration) as Time)
FROM
(
   SELECT CONCAT(u.lastname, ', ', u.firstname) AS Name
      , start.timestamp start
      , end.timestamp end
      , timediff(end.timestamp, start.timestamp) duration 
   from user u
      , user_group ug
      , (
         select *
         , (
            select event_id
            from event L2
            where L2.timestamp > L1.timestamp
               and L2.user_bannerid = L1.user_bannerid
            order by timestamp
            limit 1
           ) stop_id
         from event L1
        ) start
   join event end on end.event_id = start.stop_id
   where start.status = 'In'
      and end.status = 'Out'
   and u.user_bannerid = start.user_bannerid
   and ug.user_bannerid = u.user_bannerid
      and ug.group_id = start.group_id 
) total

它显示用户只有一次登录时的总计

+----------------------------------------------------+---------------+
| Name   | start               | end                 | duration      |    
+----------------------------------------------------+---------------+
| User   | 2011-11-24 02:12:05 | 2011-11-24 02:12:20 | 00:00:15      |       
|        |                     |                     | 00:00:15      |
+----------------------------------------------------+---------------+ 

但是当用户有多个登录时,它不会显示总小时数,

    +----------------------------------------------------+---------------+
    | Name   | start               | end                 | duration      |    
    +----------------------------------------------------+---------------+
    | User   | 2011-11-24 02:12:05 | 2011-11-24 02:12:20 | 00:00:15      |       
    | User   | 2011-11-28 21:46:54 | 2011-11-28 21:53:01 | 00:06:17      |
    |        |                     |                     |               |
    +----------------------------------------------------+---------------+

我猜测它与限制有关,但如果我将限制更改为大于1,我会得到“错误没有1242子查询返回多行”。可以有人请帮我改写查询,以显示总时数,无论他们有多少次登录?

编辑:

仍然有这个问题,所以我想出了一个新的查询,但后来我一直得到null而不是总数。 知道为什么会这样吗?

+----------------------------------------------------+---------------+
| Name   | start               | end                 | duration      |    
+----------------------------------------------------+---------------+
| User   | 2011-11-24 02:12:05 | 2011-11-24 02:12:20 | 00:00:15      |       
| User   | 2011-11-28 21:46:54 | 2011-11-28 21:53:01 | 00:06:17      |
| User   | 2011-11-28 21:46:54 | 2011-11-28 21:53:01 | null          |
+----------------------------------------------------+---------------+

SELECT
    CONCAT(u.lastname, ', ', u.firstname) AS Name,
    start.timestamp AS start,
    end.timestamp AS end,
    TIME(SUM(TIMEDIFF(end.timestamp, start.timestamp))) AS duration 
FROM user AS u
    INNER JOIN user_group AS ug ON u.user_bannerid = ug.user_bannerid
    INNER JOIN event AS start ON start.user_bannerid = u.user_bannerid AND start.status='In' AND start.group_id = ug.group_id
    INNER JOIN event AS end ON end.user_bannerid = u.user_bannerid AND end.status='Out' AND start.event_id < end.event_id 
GROUP BY start.event_id WITH ROLLUP

1 个答案:

答案 0 :(得分:0)

我认为您最好的选择是在事件表中添加stop_id,然后在用户注销时,使用Out事件中的记录ID更新In事件。

对于现有记录,您可以编写查询以根据问题中的逻辑更新记录。

执行此操作后,由于事件表中有stop_id,因此获取开始和停止时间是一个相对简单的查询。

暂时退出用户信息,这就是获取详细信息所需的全部内容:

SELECT start.timestamp start ,
       end.timestamp end ,
       timediff(end.timestamp, start.timestamp) duration 
  FROM event start join event end on end.event_id = start.stop_id

您不需要测试启动或停止状态,因为可能只有那些状态为In的事件才会有stop_id和内连接(假设是mysql中的连接)阻止Out个记录被包含在顶层。