MYSQL:使用group by获取行的“双倍”最大值

时间:2011-01-10 11:52:54

标签: mysql sql aggregate-functions

我的表:

id,user_id,street,street_number,street_stairs,street_door,zip,place,country,type

Id是主键。 类型可以是0或1。 每个user_id都可以有多个地址行。

CREATE TABLE `user_address_data` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `user_id` int(11) NOT NULL,
 `street` varchar(55) NOT NULL,
 `street_number` varchar(5) NOT NULL,
 `street_stairs` varchar(3) DEFAULT NULL,
 `street_door` varchar(3) DEFAULT NULL,
 `zip` varchar(10) NOT NULL,
 `place` varchar(30) NOT NULL,
 `country` varchar(2) NOT NULL,
 `type` tinyint(2) NOT NULL DEFAULT '0',
 PRIMARY KEY (`id`),
 UNIQUE KEY `user_id` (`user_id`,`street`,`street_number`,`street_stairs`,`street_door`,`zip`,`place`,`country`)
) ENGINE=MyISAM AUTO_INCREMENT=192 DEFAULT CHARSET=utf8

查询:

SELECT `t0`.`user_id`, `t0`.`country`
        FROM `user_address_data` as `t0` 
        INNER JOIN (SELECT `t1`.`user_id`, MAX(`t1`.`id`) as `id`
                    FROM `user_address_data` as `t1`
                    RIGHT JOIN (SELECT `user_address_data`.`user_id`, MAX(`user_address_data`.`type`) as `type`
                                FROM `user_address_data`
                                WHERE `user_address_data`.`user_id` IN (42,4, 20, 41, 43, 171)
                                GROUP BY `user_address_data`.`user_id`) as `t2`
                        ON `t2`.`user_id` = `t1`.`user_id` && `t2`.`type` = `t1`.`type`
                    GROUP BY `t1`.`user_id`) as `t3`
        ON `t3`.`id` = `t0`.`id`

问题:正如您所看到的,我正在尝试从地址表中获取最新的行。但是我需要最新行,其中“类型”字段代表 user_id 最大类型

我的想法是先为每个user_id选择max(type)。因此我能够选择每个用户的max(id)。现在我可以从字段国家/地区中选择相应的国家/地区代码。

有效,但我不认为它有效。必须创建2个临时表。有没有其他方法可以更有效地做到这一点?

感谢。

按要求,EXPLAIN SELECT:

id  select_type     table   type    possible_keys   key     key_len     ref     rows    Extra
1   PRIMARY     <derived2>  ALL     NULL    NULL    NULL    NULL    6    
1   PRIMARY     t0  eq_ref  PRIMARY     PRIMARY     4   t3.id   1    
2   DERIVED     <derived3>  ALL     NULL    NULL    NULL    NULL    6   Using temporary; Using filesort
2   DERIVED     t1  ref     user_id     user_id     4   t2.user_id  11   
3   DERIVED     user_address_data   range   user_id     user_id     4   NULL    20  Using where

1 个答案:

答案 0 :(得分:0)

我不知道你是否会在地址类型的数据中得到意外的“类型”....我不知道地址“类型”代表什么。针对单个用户采用以下方案。

User  Address ID    Type of Address
1      1            8
1      2            3
1      3            1
1      4            0

如果您获得最大地址ID(在本例中为4),并且地址的最大类型(地址ID = 1中的8),则可能导致数据不正确。也就是说,如果主要考虑的是最新的地址ID,那么你永远不需要关心max()类型的地址,因为只有一条记录与max(地址ID)相关联......所以,如果你想要基于最高类型地址的最后一个地址ID,我会选择你所描述的两个子查询(导致地址ID = 1,Type = 8)。但是如果你正在寻找(地址= 4,Type = 0,因为这是一个人的最新地址,我会修改它)。

告诉我们。

选择