LEFT JOIN只有第一行的自助表

时间:2015-09-08 22:45:07

标签: mysql sql join left-join

使用MySQL,

我有这个活动表,其中包含用户的活动:

活性

hash_id | type     | timestamp  | user  |
--------+----------+------------+-------+
abc123  |   ASSIGN | 2015-09-01 | user1 |
456def  |   ASSIGN | 2015-09-02 | user2 |
ghi789  |   ASSIGN | 2015-09-05 | user3 |
012jkl  |   ASSIGN | 2015-09-10 | user4

我希望得到'ASSIGN'活动的历史告诉用户N,它何时被分配,但是当它被取消分配时,被分配给其他人。 (可能还有其他类型的活动,这里会被忽略)

这样的事情:

start      | end        | user
-----------+------------+-------
2015-09-01 | 2015-09-02 | user1
2015-09-02 | 2015-09-05 | user2
2015-09-05 | 2015-09-10 | user3
2015-09-10 | NA         | user4

对于任何用户N,属于另一个不同用户的未来ASSIGN事件意味着对其进行解除分配。

如果对于某些用户N,将来没有ASSIGN到不同用户的事件,那么结束列可能会说“NA”。这意味着当前已分配userN。

所以,我认为解决方案可能来自活动表的LEFT JOIN。但是目前我只能得到一些令人困惑的活动历史记录,包括用户的每个时间戳,与桌面上的其他活动相关。

我得到了:

start      | end        | user
-----------+------------+-------
2015-09-01 | 2015-09-02 | user1
2015-09-01 | 2015-09-05 | user1
2015-09-01 | 2015-09-10 | user1
2015-09-02 | 2015-09-05 | user2
2015-09-02 | 2015-09-10 | user2
2015-09-05 | 2015-09-10 | user3
2015-09-10 | NA         | user4

我注意到JOIN正在检索活动和未来活动之间的所有关系,事实上如果我能够检索JOIN的第一个结果,这可以解决。这就是我被困住的地方。

我目前正在玩两个可能的查询,两个都给我相同的结果::

这是我的第一次尝试:

   SELECT a.timestamp AS start,
          COALESCE(endac.timestamp,'NA') AS end,
          a.user
     FROM activity a
LEFT JOIN 
          (SELECT ac.timestamp, ac.groupkey, ac.assigneduserkey, ac.type
             FROM activity jac
            WHERE jac.type='ASSIGN'
          ) endac
       ON (endac.user <> a.user AND endac.timestamp > a.timestamp)
    WHERE a.type = 'ASSIGN'

另一个来自我在LEFT JOIN only first row读到的内容:

   SELECT a.timestamp AS start,
          COALESCE(endac.timestamp,'NA') AS end,
          a.user
     FROM activity a
LEFT JOIN activity endac
       ON (endac.hash_id = (SELECT jact.hash_id
                              FROM activity jact
                             WHERE jact.hash_id=endac.hash_id
                               AND jact.type = 'ASSIGN'
                               AND jact.user <> a.user
                               AND jact.timestamp > a.timestamp
                             LIMIT 1
                           )
          )
    WHERE a.type = 'ASSIGN'

有什么建议吗?我是否在正确的轨道上寻找我需要的东西?如何获得JOIN的第一行,以便我得到正确的结果?

1 个答案:

答案 0 :(得分:1)

这应该不那么复杂了!

SELECT
  plus.timestamp AS start,
  IFNULL(MIN(minus.timestamp),'NA') AS end,
  plus.user AS user
FROM
  activity AS plus
  LEFT JOIN activity AS minus
    ON minus.timestamp>plus.timestamp
GROUP BY plus.timestamp
ORDER BY plus.timestamp
;

给出了预期的输出,但是效率非常低。

SQLfiddle