【问题标题】:LEFT JOIN with self table only first rowLEFT JOIN 仅与 self 表的第一行
【发布时间】:2015-12-04 18:22:15
【问题描述】:

在 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

我希望通过被分配给其他人来为用户 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

对于任何 userN,属于另一个不同用户的未来 ASSIGN 事件意味着取消分配它。

如果对于某些用户 N 没有未来的 ASSIGN-to-a-different-user 事件,那么结尾列可能会显示为“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 的第一行以便获得正确的结果?

【问题讨论】:

    标签: mysql sql join left-join


    【解决方案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

    【讨论】:

    • 我希望至少有一个 WHERE 条件和一个 ON 条件来过滤掉不是“ASSIGN”的活动
    • @JavierNovoaC。当然 - 我省略了您的测试数据不需要的所有内容,简单的 ON .. AND minus.type = 'ASSIGN'WHERE plus.type = 'ASSIGN' 就足够了。
    • 你是对的,正在对我的几个数据进行测试并且它正在工作!谢谢:D
    猜你喜欢
    • 2013-03-15
    • 1970-01-01
    • 2020-08-02
    • 2013-11-18
    • 2017-03-16
    • 2017-04-29
    • 2014-05-01
    • 1970-01-01
    相关资源
    最近更新 更多