【问题标题】:CakePHP find with MAXCakePHP 用 MAX 查找
【发布时间】:2012-01-14 23:14:36
【问题描述】:

表格和虚拟数据:

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');

我想要的是来自另一个用户的特定用户的最新消息。例如:Facebook Inbox,您可以在其中找到与人的对话以及按时间顺序排列的最后一次对话和时间。

我尝试了什么:

$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')),
        ),
    ),
));

我得到了什么:

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
                                )

                        )

                )

        )

)

我没有收到返回 id: 4 和 7 的消息。

SQL 转储

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)

【问题讨论】:

  • 您为 4 号节点创建的日期早于 3 号节点。这似乎不正确。
  • 数字 5,6 用于节点 3.. 数字 7,8 用于节点 4

标签: php mysql cakephp cakephp-1.3 max


【解决方案1】:

尝试通过将其放在您的视图中来查看您的 SQL 调试日志:

$this->Element('sql_dump');

请注意,仅当您的调试级别不为零时才会产生输出。我怀疑您的 MAX 查询仅选择一个具有最高值的节点,因此不会返回任何其他节点。按 created 排序而不是用 MAX 选择它是我最好的选择。

【讨论】:

  • 此外,当您执行以下操作时,使用 MAX 等聚合函数确实会为 id 生成所需的结果:SELECT id, MAX(created) FROM messages。如果您想要具有最新时间戳的消息 id,您需要使用类似:SELECT id, created FROM messages ORDER BY created DESC LIMIT 1。
【解决方案2】:

如果我对您的理解正确,这将为您提供所需的结果:

$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'));

这应该为您提供 3 个结果,每个用户一个。

【讨论】:

  • 请注意,在使用 group by 子句时,字段 * 在所有技术上都是错误的,但这与问题无关。
  • 我仍然只得到一个结果.. Array ( [0] => Array ( [0] => Array ( [created] => 2011-12-07 12:00:00 ) [Message ] => 数组 ( [id] => 1 [user_id] => 1 [node_id] => 1 [reciever_id] => 15 [创建] => 2011-12-07 00:00:00 [修改] => 2011 -12-07 02:00:00 ) ) )
  • 应该创建的sql是SELECT MAX(Node.created),* FROM messages AS Message, nodes AS Node WHERE Message.node_id = Node.id GROUP BY Message.user_id。在您的数据库中运行此查询,它应该返回正确的结果。但我相信您还有其他影响 cakephp 创建的查询的数据库关系。
  • 我认为这是您使用我的建议之前的 sql 转储。您能否使用我的代码 sn-p 给出 sql 的转储?
  • 它提供了相同的东西,但没有包含
【解决方案3】:

这是Example using GROUP BY 标题下的解决方案。对我有用的是:

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

为每个wantunique 字段生成一个具有最高wanthighest 字段的数组。我发现向字段选项添加字段是没有意义的,因为 CakePHP 不会从数组项的同一行获取字段。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    相关资源
    最近更新 更多