Zend DB объединяет 2 строки из одной таблицы - PullRequest
1 голос
/ 21 сентября 2011

У меня есть следующая таблица.

---------------------------------------------
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 Ответ

1 голос
/ 21 сентября 2011

Попробуйте этот запрос, без группы по :

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 и c2 указывают на одну и ту же строку.

Затем вы используете GROUP BY, которая объединяет несколько строк в одну, но MySQL выбирает произвольную строку из группы. (Это неоднозначный запрос, и если вы SET SQL_MODE='ONLY_FULL_GROUP_BY' получите сообщение об ошибке.)

Таким образом, ваше самообъединение и только GROUP BY возвращают c1 и c2, которые на самом деле являются одной и той же строкой.

Чтобы это исправить, вы должны добавить условие, что c1.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, при условии, что у вас нет нескольких начальных и конечных значений для каждого действия.

Кстати, этот тип сложности является одной из причин, по которой обычно рекомендуется хранить данные начала / окончания события в одной строке, где начало в одном столбце, а конец во втором столбце.

...