Zend DB从同一个表中加入2行

时间:2011-09-20 21:09:05

标签: zend-framework join zend-db zend-db-table

我有下表。

---------------------------------------------
check_id | action_id | user_id |         dt |
---------------------------------------------
       1 |         1 |       6 | 2011-09-17 |
       2 |         1 |       6 | 2011-09-18 |
       3 |         3 |       6 | 2011-09-19 |
       4 |         3 |       6 | 2011-09-20 |
---------------------------------------------

我想查询此表并获得以下结果。

-----------------------------------------------
action_id | user_id |   dt_start |     dt_end |
-----------------------------------------------
       1 |        6 | 2011-09-17 | 2011-09-18 |
       3 |        6 | 2011-09-19 | 2011-09-20 |
-----------------------------------------------

所以我使用以下查询。

$checks->select()
->from(array('c1' => 'checks'), array('dt as dt_start')
->joinLeft(array('c2' => 'checks'), 'c1.action_id = c2.action_id', array('dt as dt_end')
->where('c1.user_id = ?', $userId)
->group('c1.action_id')

但是这给了我以下结果。

-----------------------------------------------
action_id | user_id |   dt_start |     dt_end |
-----------------------------------------------
       1 |        1 | 2011-09-17 | 2011-09-17 |
       1 |        3 | 2011-09-19 | 2011-09-19 |
-----------------------------------------------

有人能告诉我我做错了吗?

1 个答案:

答案 0 :(得分:1)

尝试此查询,不带的小组:

SELECT *
FROM checks c1 LEFT OUTER JOIN checks c2 ON c1.action_id = c2.action_id 
WHERE c1.user_d = 6

你会看到你得到的比赛是c1.dt< c2.dt,这就是你想要的。 但你也得到匹配c1.dt> c2.dt,其中c1.dt = c2.dt. 也就是说,自联接包括c1和c2指向同一行的结果。

然后使用GROUP BY将多行折叠成一行,但MySQL选择该组中的任意行。 (这是一个含糊不清的查询,如果你SET SQL_MODE='ONLY_FULL_GROUP_BY',你会收到错误。)

所以你的自我加入和GROUP BY 返回实际上是同一行的c1和c2。

要解决此问题,您应该添加一个条件c1.dt< c2.dt.

$checks->select()
->from(array('c1' => 'checks'), array('dt as dt_start')
->joinLeft(array('c2' => 'checks'), 
           'c1.action_id = c2.action_id AND c1.dt < c2.dt', 
           array('dt as dt_end')
->where('c1.user_id = ?', $userId)

在这种情况下,您可能根本不需要GROUP BY,假设您没有多个开始和结束每个操作。

顺便说一下,这种复杂性是一个原因,通常建议将事件开始/结束数据存储在一行中,一行开始,第二列结束。