2011-12-07 12 views
10

Tablas y datos ficticios:CakePHP encuentran con MAX

CREATE TABLE IF NOT EXISTS `messages` (
    `id` int(11) unsigned NOT NULL auto_increment, 
    `user_id` int(11) unsigned NOT NULL, 
    `node_id` int(11) unsigned NOT NULL, 
    `reciever_id` int(11) unsigned NOT NULL, 
    `created` datetime default NULL, 
    `modified` datetime default NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ; 


INSERT INTO `messages` (`id`, `user_id`, `node_id`, `reciever_id`, `created`, `modified`) VALUES 
(1, 1, 1, 15, '2011-12-07 00:00:00', '2011-12-07 02:00:00'), 
(2, 15, 1, 1, '2011-12-07 02:00:00', '2011-12-07 02:00:00'), 
(3, 15, 2, 1, '2011-12-07 11:00:00', '2011-12-07 11:00:00'), 
(4, 1, 2, 15, '2011-12-07 11:00:00', '2011-12-07 11:00:00'), 
(5, 1, 3, 18, '2011-12-07 12:00:00', '2011-12-07 12:00:00'), 
(6, 18, 3, 1, '2011-12-07 12:00:00', '2011-12-07 12:00:00'), 
(7, 1, 4, 18, '2011-12-07 07:00:00', '2011-12-07 07:00:00'), 
(8, 18, 4, 1, '2011-12-07 07:00:00', '2011-12-07 07:00:00'); 


CREATE TABLE IF NOT EXISTS `nodes` (
    `id` int(11) unsigned NOT NULL auto_increment, 
    `message` text NOT NULL, 
    `author_id` int(11) unsigned NOT NULL, 
    `read` tinyint(1) default NULL, 
    `created` datetime default NULL, 
    `modified` datetime default NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ; 



INSERT INTO `nodes` (`id`, `message`, `author_id`, `read`, `created`, `modified`) VALUES 
(1, 'Hi! How are you ? dude wanna meet up this weekend ?', 1, 0, '2011-12-07 02:00:00', '2011-12-07 02:00:00'), 
(2, 'Sure. wanna go to Mangalore Pearl to eat Neer Dosa..', 15, 0, '2011-12-07 11:00:00', '2011-12-07 11:00:00'), 
(3, 'Hi How are u Buddy ? Long time no see...', 1, 0, '2011-12-07 12:00:00', '2011-12-07 12:00:00'), 
(4, 'yeah. are you back in town ? i think we should meet up man. its been ages ....', 18, 0, '2011-12-07 07:00:00', '2011-12-07 07:00:00'); 

Lo que yo quiero es el último mensaje de un usuario determinado de otro usuario. Por ejemplo: Bandeja de entrada de Facebook, donde encuentras conversaciones con personas y la última conversación y hora en el orden del tiempo.

lo que he intentado:

$messages = $this->User->Message->find('all', array('conditions' => array('user_id' => 
     $user_id), 'group by' => 'Message.reciever_id', 'order' => 
     'Message.created DESC', 'fields' => array('MAX(Message.created)', '*'), 
     'contain' => array('Node' => array('fields' => array('id', 'message', 
     'author_id', 'read', 'created')), 'Reciever' => array('fields' => array('id', 
     'first_name', 'last_name'), 'Oauth' => array('fields' => array('provider_uid')))))); 

Lo que tengo:

Array (
    [0] => Array 
     (
      [0] => Array 
       (
        [MAX(`Message`.`created`)] => 2011-12-07 12:00:00 
       ) 

      [Message] => Array 
       (
        [id] => 1 
        [user_id] => 1 
        [node_id] => 1 
        [reciever_id] => 15 
        [created] => 2011-12-07 00:00:00 
        [modified] => 2011-12-07 02:00:00 
       ) 

      [Node] => Array 
       (
        [id] => 1 
        [message] => Hi! How are you ? dude wanna meet up this weekend ? 
        [author_id] => 1 
        [read] => 0 
        [created] => 2011-12-07 02:00:00 
       ) 

      [Reciever] => Array 
       (
        [id] => 15 
        [first_name] => Mayur 
        [last_name] => Polepalli 
        [Oauth] => Array 
         (
          [0] => Array 
           (
            [provider_uid] => 551131489 
            [id] => 15 
            [user_id] => 15 
           ) 

         ) 

       ) 

     ) 

) 

No estoy recibiendo los mensajes con el identificador: 4 y 7 devueltos.

SQL DUMP

SELECT MAX(`Message`.`created`), `Message`.*, `Node`.`id`, `Node`.`message`, `Node`.`author_id`, `Node`.`read`, `Node`.`created`, `Reciever`.`id`, `Reciever`.`first_name`, `Reciever`.`last_name` FROM `messages` AS `Message` LEFT JOIN `nodes` AS `Node` ON (`Message`.`node_id` = `Node`.`id`) LEFT JOIN `users` AS `Reciever` ON (`Message`.`reciever_id` = `Reciever`.`id`) WHERE `user_id` = 1 ORDER BY `Message`.`created` DESC 

SELECT `Node`.`id`, `Node`.`message`, `Node`.`author_id`, `Node`.`read`, `Node`.`created` FROM `nodes` AS `Node` WHERE `Node`.`id` = 1 

SELECT `Reciever`.`id`, `Reciever`.`first_name`, `Reciever`.`last_name` FROM `users` AS `Reciever` WHERE `Reciever`.`id` = 15 

SELECT `Oauth`.`provider_uid`, `Oauth`.`id`, `Oauth`.`user_id` FROM `oauths` AS `Oauth` WHERE `Oauth`.`user_id` = (15) 
+0

Su fecha de creación para el nodo número 4 es anterior al número de nodo 3. Esto no parece correcto. – Nightwolf

+0

número 5,6 es para el nodo 3 .. número 7,8 para el nodo 4 –

Respuesta

9

Si te estoy entendiendo correctamente este le daría el resultado deseado:

$messages = $this->User->Message->find('all', array(
    'conditions' => array('user_id' => $user_id), 
    'fields' => array('MAX(Node.created) AS created', '*'), 
    'group by' => 'Message.user_id', 
    'order' => 'reciever_id')); 

Esto debe darle 3 resultados, uno para cada usuario.

+1

Tenga en cuenta que El campo * está mal en todos los aspectos técnicos al usar la cláusula group by, pero eso no es relevante para la pregunta. – Nightwolf

+0

todavía recibo un solo resultado.Matriz ( [0] => Array ( [0] => Array ( [creado] => 2011-12-07 12:00:00 ) [Mensaje] => Array ( [id] => 1 [user_id] => 1 [node_id] => 1 [id_recedor] => 15 [created] => 2011-12-07 00:00:00 [modified] => 2011 -12-07 02:00:00 ) ) ) –

+0

El SQL que debe crearse es 'SELECT MAX (Node.created), * FROM messages AS Message, nodes AS Node WHERE Message.node_id = Node.id GROUP BY Message.user_id'. Ejecute esta consulta en su base de datos y debería regresar con los resultados correctos. Pero creo que tienes otras relaciones con la base de datos que influyen en la consulta que cakephp crea. – Nightwolf

1

intente buscar en el registro de depuración de SQL poniendo esto en su vista:

$this->Element('sql_dump'); 

Tenga en cuenta que esto sólo se produce una salida si su nivel de depuración no es cero. Sospecho que su consulta MAX solo selecciona un solo nodo con el valor más alto y, por lo tanto, no devuelve ningún otro nodo. Ordenar por creado en lugar de seleccionarlo con MAX sería mi mejor opción para poner esto en marcha.

+1

Además, el uso de funciones agregadas, como MAX, produce el resultado deseado para id cuando haces algo como: SELECT id, mensajes MAX (creados) FROM . Si desea la identificación del mensaje con la última marca de tiempo, debe usar algo como: SELECCIONAR ID, crear mensajes DESDE ORDEN POR DESC LIMITE creado 1. –

+0

He actualizado la pregunta y agregué el VOLCADO SQL –

1

Aquí hay una solución bajo el título Example using GROUP BY. Lo que funcionó para mí está en la línea de:

$this->Model->find('all', array(
    'fields' => 'MAX(Model.wanthighestfield) as wanthighestfield', 
    'group' => 'wantuniquefield' 
)); 

resultados en una matriz con la más alta wanthighestfield para cada wantuniquefield. Descubrí que agregar campos a las opciones de campos no tiene sentido ya que CakePHP no buscará los campos de la misma línea para el elemento de la matriz.