1

I've created an insert only table for the purpose of speed and maintaining a history. It's structure is very generic, and is as follows:

  `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;

It's simply a key/value table with a user_id assigned to it. This approach has its advantages as not all users have the same properties, so fields aren't wasted in a table. Also, it allows for a rolling log of changes, since I can see every change to a particular property ever made by a user.

Now, since no deletes or updates ever occur in this table, I can assume that the greatest id will always be the newest entry.

However, I want to select multiple properties at once, for example 'address1', 'address2', 'city', 'state', and I want each to be the entry of it's type with the highest id.

So, if they have changed their 'state' property 8 times, and 'city' property 4 times, then I'd only want a SELECT to return the latest of each (1 state and 1 city).

I'm not sure this can even be done efficiently with this type of a table, so I'm open to different table approaches.

Please, let me know if I need to produce anymore information or clarify my question better.

=== I tried the following, but, there could be 3 rows of 'address1' changes after the last 'address2' change. Perhaps using a GROUP BY will work?

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

4

1 回答 1

4

假设您的 id 是增量整数并且您没有手动指定它们乱序,您可以在子查询中使用一些MAX()聚合来执行此操作。子查询的重点是为每个用户返回每个属性名称的最新条目。这与整个表相结合,以提取相关的属性值。本质上,子查询丢弃每组没有 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
于 2012-05-29T14:11:05.770 回答