1

Working on MySQL,

I have this activity table with events for users:

activity

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

I wish to get the history of 'ASSIGN' activities telling for userN, when was it ASSIGNed, but also when was it deASSIGNed, by being ASSIGNed to somebody else. (There may be other type of activities, which are ignored here)

Something like this:

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

For any userN, a future ASSIGN event belonging to another different user means deASSIGNing it.

If for some userN there's no future ASSIGN-to-a-different-user event, then the end column may say something as 'NA'. This means that userN is currently assigned.

So, I think a solution might come from a LEFT JOIN of the activity table with itself. But currently I can only get some confusing history of activities, with every timestamp for a user, related with every other activity on the table.

I'm getting:

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

I noted that the JOIN is retreiving all the relations between an activity and future activities and in fact this could be solved if I can just retrieve the first result of the JOIN. And this is where I'm stuck.

I am currently playing with two possible queries, both throw me the same result::

this is my first try:

   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'

this other one came from what I read at 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'

any suggestions? am I on the right track for what I need? How to get just the first row of the JOINs so that I can get the right result?

Community
  • 1
  • 1
Javier Novoa C.
  • 11,257
  • 13
  • 57
  • 75

1 Answers1

1

This should be less complicated!

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
;

gives the expected output, but is ofcourse horribly inefficient.

SQLfiddle

Eugen Rieck
  • 64,175
  • 10
  • 70
  • 92
  • I guest that at least a WHERE condition, and a ON condition, should be made to filter out activities not being 'ASSIGN' – Javier Novoa C. Sep 08 '15 at 23:03
  • 1
    @JavierNovoaC. Of course - I left out everything not needed for your test data, a simple `ON .. AND minus.type = 'ASSIGN'` and `WHERE plus.type = 'ASSIGN'` is sufficient. – Eugen Rieck Sep 09 '15 at 07:48
  • you are right, being testing it for several of my data and it's working! thanks :D – Javier Novoa C. Sep 09 '15 at 16:40