【问题标题】:MySQL: Calculate the duration for multiple statusesMySQL:计算多个状态的持续时间
【发布时间】:2012-10-03 13:57:41
【问题描述】:

我有一个包含俱乐部会员信息的数据库。每个成员在任何时候都可以是三种不同状态之一(活跃、老手、助理)。我把它分解成三个表。成员表,包含所有成员信息,状态表包含 status_name 和 status_id,以及一个包含 member_id、status_id、date_from 和 date_to 的网格表。

我正在尝试计算会员在每种状态下花费的时间。我目前正在通过以下查询计算会员处于“活动”状态的总时间:

SELECT first_name, last_name, 
 (DATE_FORMAT( FROM_DAYS( SUM( DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) ) , "%Y" ) +0) as service_years 
 FROM member a
 LEFT JOIN member_status q on a.id = q.member_id AND q.status_id = 1
 GROUP BY a.id

我知道我可以通过在左连接中去掉 AND 来提取该人成为成员的总时间,但是我无法找到一种方法来计算单个查询中每个状态的时间。

我的理想结果是:

 -----------------------------------------------------------
 |member_name | active_years | veteran_years | total_years |
 -----------------------------------------------------------
 |name        | 5            | 5             | 10          |
 -----------------------------------------------------------

有没有办法在单个查询中完成我要查找的内容?

【问题讨论】:

    标签: mysql sql left-join aggregate datediff


    【解决方案1】:

    假设 1=active 和 2=veteran,这样的事情应该可以工作:

    SELECT first_name, last_name, 
     (DATE_FORMAT( FROM_DAYS( SUM( case when q.status_id = 1 then DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) else 0 end ) , "%Y" ) +0) as active_years,
     (DATE_FORMAT( FROM_DAYS( SUM( case when q.status_id = 2 then DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) else 0 end ) , "%Y" ) +0) as veteran_years,
    (DATE_FORMAT( FROM_DAYS( SUM( DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) ) , "%Y" ) +0) as total_years 
     FROM member a
      LEFT JOIN member_status q on a.id = q.member_id AND q.status_id in (1,2)
     GROUP BY a.id
    

    另一种选择是多次加入 member_status 表。

    【讨论】:

      【解决方案2】:

      你应该能够做这样的事情,它使用CASE 语句来确定状态名称,然后根据状态计算总年数:

      SELECT first_name, 
        last_name, 
        CASE WHEN status_name = 'active' 
          then (DATE_FORMAT( FROM_DAYS( SUM( DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) ) , "%Y" ) +0) end as active_years,
        CASE WHEN status_name = 'veteran' 
          then (DATE_FORMAT( FROM_DAYS( SUM( DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) ) , "%Y" ) +0) end as active_years,
        (DATE_FORMAT( FROM_DAYS( SUM( DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) ) , "%Y" ) +0) as total_years,
      FROM member a
      LEFT JOIN member_status q 
        on a.id = q.member_id 
        AND q.status_id = 1
      GROUP BY a.id, a.first_name, a.last_name
      

      如果您发布一些示例数据,将更容易确定正确的查询

      【讨论】:

        猜你喜欢
        • 2021-09-02
        • 2018-08-22
        • 1970-01-01
        • 2011-07-30
        • 2021-09-27
        • 2021-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多