2012-05-29 46 views
1

我已经创建了一个仅用于插入表格以达到速度和保持历史记录的目的。它的结构是非常通用的,如下:SQL只插入表格,如何只选择最新的条目

`id` bigint(20) unsigned NOT NULL auto_increment, 
    `user_id` bigint(20) unsigned NOT NULL, 
    `property` varchar(32) NOT NULL, 
    `value` longblob NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1; 

它只是一个键/值表与分配给它的USER_ID。这种方法有其优点,因为并非所有用户都具有相同的属性,所以字段不会浪费在表中。此外,它还允许滚动记录更改,因为我可以看到用户所做的特定属性的每个更改。

现在,由于此表中没有发生任何删除或更新,我可以假设最大的id始终是最新的条目。然而,我想一次选择多个属性,例如'address1','address2','city','state',我希望每个属性都是其最高id的类型的入口。因此,如果他们已经8次更改了他们的'州'属性,'城市'属性更改了4次,那么我只想要一个SELECT返回每个(1个州和1个城市)的最新值。

我不确定这个表格甚至可以用这种类型的表格高效地完成,所以我打开了不同的表格方法。

请让我知道如果我需要生产更多的信息或更好地澄清我的问题。

=== 我尝试了以下操作,但最后一次'address2'更改后可能会有3行'address1'更改。也许使用GROUP BY会起作用吗?

SELECT property, value FROM kvtable WHERE user_id = 1 AND (property = 'address1' OR property = 'address2') ORDER BY id

+1

“*现在,由于此表中没有删除或更新,我可以假定最大的id始终是最新的条目*” - 不,你不能。如果一个'INSERT'指定一个明确的'id' ***'x' ***,那么稍后一个指定明确的'''''***''''''''''***'x' ***? – eggyal

+0

这是自动增量,不应该明确定义。这仍然是一个安全的假设?我可以添加一个日期列。 – crush

+1

仅仅因为定义了一个列'AUTO_INCREMENT'并不能阻止用户在'INSERT'期间提供明确的值 - 如果没有提供明确的值,它仅仅设置一个递增的值。一般来说,时间戳列更安全;然而,如果你完全控制了每个'INSERT'操作,并且可以确保没有提供明确的'id',我*认为*安全工作的前提是'id'在插入时会严格增加。 – eggyal

回答

4

假设你的ID是增量整数和你没有手动指定出来的顺序,你可以在一个子查询的几个MAX()聚集做到这一点。子查询的重点是为每个用户返回每个属性名称的最新条目。这与整个表格连接以提取相关的属性值。本质上,子查询会丢弃每个组中没有最大(id)的所有行。

SELECT kvtable.* 
FROM 
    kvtable 
    JOIN (
    SELECT 
     MAX(id) AS id, 
     user_id, 
     property 
    FROM kvtable 
    /* optionally limit by user_id */ 
    WHERE user_id = <someuser> 
    GROUP BY user_id, property 
) maxids ON kvtable.id = maxids.id 
+0

这似乎是做这项工作。现在,如果我想限制它到指定ID的用户,我会追加做JOIN ON语句为'ON properties_table.id = maxids.id AND properties_table.user_id = 1'例如? – crush

+1

@crush是的,在ON子句中,或者你可以在子查询中添加一个WHERE子句。 –

+0

太棒了。无论如何,这似乎足够有效。谢谢您的帮助! – crush