我想在数据库中为表创建一个视图,这样我就可以更容易地在连接中使用它。表UserSettings
看起来像这样:
mysql> desc UserSettings; -- cut the output for readability
+-----------+---------------------
| Field | Type
+-----------+---------------------
| userID | bigint(20) unsigned
| timestamp | timestamp
| settingID | text
| setting | text
+-----------+---------------------
4 rows in set (0.00 sec)
在其中我们存储用户设置的每个更新。现在我想为这个表创建一个视图,其中包含每个用户的最新设置。所以我希望视图包含标有*
的行:
mysql> select * from UserSettings;
+--------+---------------------+-----------------------+---------+
| userID | timestamp | settingID | setting |
+--------+---------------------+-----------------------+---------+
| 123 | 2014-04-16 12:08:30 | settings.warnings_off | 1 |
| 123 | 2014-04-16 12:18:56 | settings.warnings_off | 0 |
| 123 | 2014-04-17 06:42:08 | settings.warnings_off | 1 |
| 123 | 2014-04-17 06:49:08 | settings.warnings_off | 0 | *
| 911 | 2014-04-17 06:49:33 | settings.warnings_off | 1 | *
| 123 | 2014-04-17 10:04:12 | settings.test | fooo |
| 123 | 2014-04-17 10:04:22 | settings.test | bar | *
| 911 | 2014-04-17 10:07:40 | settings.test | bar | *
+--------+---------------------+-----------------------+---------+
8 rows in set (0.00 sec)
我可以使用包含子查询的查询来执行此操作:
mysql> SELECT us.*
-> FROM UserSettings us INNER JOIN (
-> SELECT userID, settingID, max(timestamp) as timestamp
-> from UserSettings
-> group by userID, settingID) ts ON ts.userID = us.userID AND
-> ts.settingID = us.settingID AND ts.timestamp = us.timestamp;
+--------+---------------------+-----------------------+---------+
| userID | timestamp | settingID | setting |
+--------+---------------------+-----------------------+---------+
| 123 | 2014-04-17 10:04:22 | settings.test | bar |
| 123 | 2014-04-17 06:49:08 | settings.warnings_off | 0 |
| 911 | 2014-04-17 10:07:40 | settings.test | bar |
| 911 | 2014-04-17 06:49:33 | settings.warnings_off | 1 |
+--------+---------------------+-----------------------+---------+
4 rows in set (0.00 sec)
但是,在ERROR 1349 (HY000): View's SELECT contains a subquery in the FROM clause
中使用上述查询时,我收到错误CREATE VIEW CurrentUserSettings AS <THE QUERY ABOVE>
。
有没有办法创建UserSettings
表的视图,显示与上述查询相同的数据?也许以某种方式使用HAVING
?
答案 0 :(得分:2)
扩展我的评论: -
CREATE VIEW latest_timestamp AS SELECT userID, settingID, max(timestamp) as timestamp
from UserSettings
group by userID, settingID;
CREATE VIEW latest_timestamp AS SELECT us.*
FROM UserSettings us
INNER JOIN latest_timestamp ts
ON ts.userID = us.userID AND
ts.settingID = us.settingID
AND ts.timestamp = us.timestamp;
另一种选择是(ab)使用GROUP_CONCAT函数。我并不热衷于这样做,如果字段可以包含NULL,则存在问题,并且需要将整数转换为字符字段。
假设你想要的字段叫做field1,field2和field3,那么: -
SELECT us.userID,
us.settingID,
SUBSTRING_INDEX(GROUP_CONCAT(us.field1 ORDER BY timestamp DESC SEPARATOR '|~|~'), '|~|~', 1),
SUBSTRING_INDEX(GROUP_CONCAT(us.field2 ORDER BY timestamp DESC SEPARATOR '|~|~'), '|~|~', 1),
SUBSTRING_INDEX(GROUP_CONCAT(us.field3 ORDER BY timestamp DESC SEPARATOR '|~|~'), '|~|~', 1)
FROM UserSettings us
GROUP BY us.userID, us.settingID;
这可以通过将一个字段的所有值连接成一个,按时间戳降序排序,并在它们之间有一个分隔符(不在任何字段中),然后使用SUBSTRING_INDEX将字段设置为第一个分隔符。
答案 1 :(得分:1)
像Kickstart建议的那样,喜欢这个
首先,在视图中创建子查询
CREATE VIEW subqueryview as
SELECT userID, settingID, max(timestamp) as timestamp
from UserSettings group by userID, settingID;
然后您可以使用视图创建视图。
CREATE VIEW finalview AS
SELECT us.*
FROM UserSettings us
-- Here you now use the view created.
INNER JOIN subqueryview ts
ON ts.userID = us.userID
AND ts.settingID = us.settingID
AND ts.timestamp = us.timestamp;