我遇到了一个相当奇怪的问题。我在mysql数据库中使用以下示例数据:
|key| data| index | total | timestamp | | # | a | 1 | 2 | 2009-01-02 01:01:32 | | $ | b | 2 | 2 | 2009-01-02 01:03:32 | | % | c | 1 | 3 | 2009-01-03 01:01:32 | | ^ | d | 2 | 3 | 2009-01-03 01:04:32 | | & | e | 3 | 3 | 2009-01-03 01:02:32 | | * | f | 1 | 2 | 2009-01-05 01:01:32 |
正在发生的是另一个进程(不在我的控制之下)正在接收数据包,并将它们直接存储到数据库中,并带有到达时间的时间戳。假设分组以突发方式到达... a,b将彼此靠近并且被索引为1和2,每个分组包含发送的“总”分组数。 key是正常的自动递增主键。
我需要的是一个视图,它将显示已到达的最新列表(部分列表,如果不是所有数据包都已到达,则可以接受)。
对于上面的查询,理想情况下结果应该只是“f”,但我没有办法做到这一点。如果我们不能以另一种方式得到它,那么返回“a”和“f”将是可以接受的。换句话说,select语句捕获的少量额外数据不是一个大问题。在“f”到达之前的一段时间内,正确的回报是c,d和e。
我的一般想法是:
SELECT * FROM table WHERE total = ( SELECT total FROM table WHERE timestamp = ( SELECT MAX(timetamp) FROM table ) ) ORDER BY DESC timestamp LIMIT ( SELECT total FROM table WHERE timestamp = ( SELECT MAX(timetamp) FROM table )
正如你们中的一些人可能已经注意到的那样,你们不能在LIMIT子句中做一个子查询(至少使用mysql)。有没有人有另一种方法来解决这个问题?通过将JOIN嵌套到最近的id的小列表中,可以使上面的查询变得更加清晰,但是仍然会在子查询中留下LIMIT子查询问题。
作为一个两阶段的查询,这是相对微不足道的。问题是它需要成为VIEW的定义select语句。
编辑修复错误的sql示例
答案 0 :(得分:1)
查询我建议:
SELECT *
FROM packets
WHERE total = ( SELECT total
FROM packets
WHERE timestamp = ( SELECT MAX(timestamp) FROM packets ))
AND timestamp >= ( SELECT MAX(timestamp) FROM packets WHERE idx = 1 )
ORDER BY timestamp DESC;
无为:
mysql> create table packets( id bigint(20) AUTO_INCREMENT primary key, data char(1), idx int(10), total int(10), timestamp datetime );
Query OK, 0 rows affected (0.00 sec)
mysql> insert into packets( data, idx, total, timestamp ) values( 'a', 1 ,2,'2009-01-02 01:01:32'),
-> ('b' ,2 ,2,'2009-01-02 01:03:32'),
-> ('c' ,1 ,3,'2009-01-03 01:01:32'),
-> ('d' ,2 ,3,'2009-01-03 01:04:32'),
-> ('e' ,3 ,3,'2009-01-03 01:02:32'),
-> ('f' ,1 ,2,'2009-01-05 01:01:32');
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> SELECT *
-> FROM packets
-> WHERE total = ( SELECT total
-> FROM packets
-> WHERE timestamp = ( SELECT MAX(timestamp) FROM packets ))
-> AND timestamp >= ( SELECT MAX(timestamp) FROM packets WHERE idx = 1 )
-> ORDER BY timestamp DESC;
+----+------+------+-------+---------------------+
| id | data | idx | total | timestamp |
+----+------+------+-------+---------------------+
| 6 | f | 1 | 2 | 2009-01-05 01:01:32 |
+----+------+------+-------+---------------------+
1 row in set (0.00 sec)
mysql> delete from packets where id = 6;
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM packets WHERE total = ( SELECT total FROM packets WHERE timestamp = ( SELECT MAX(timestamp) FROM packets )) AND timestamp >= ( SELECT MAX(timestamp) FROM packets WHERE idx = 1 ) ORDER BY timestamp DESC;
+----+------+------+-------+---------------------+
| id | data | idx | total | timestamp |
+----+------+------+-------+---------------------+
| 4 | d | 2 | 3 | 2009-01-03 01:04:32 |
| 5 | e | 3 | 3 | 2009-01-03 01:02:32 |
| 3 | c | 1 | 3 | 2009-01-03 01:01:32 |
+----+------+------+-------+---------------------+
3 rows in set (0.00 sec)
mysql>
答案 1 :(得分:0)
如果它们按顺序到达而没有在其间写入其他数据包,则以下内容也应该有效。
SELECT *
FROM Total t
INNER JOIN (
SELECT Total, Timestamp
FROM Total t
INNER JOIN (
SELECT Timestamp = MAX(Timestamp)
FROM Total
WHERE ID = 1
) ts ON ts.Timestamp = t.Timestamp.
) tit ON tit.Total = t.Total AND tit.Timestamp <= t.Timestamp
答案 2 :(得分:0)
这是我在sql server中的方法,你可以转换为mysql语法。
SELECT *
FROM table
INNER JOIN (SELECT TOP 1 * FROM table ORDER BY key DESC) AS t ON (table.timestamp = t.timestamp AND table.total = t.total)
答案 3 :(得分:0)
我最终得到的查询格式略有不同:
CREATE VIEW NewestTimestamps AS SELECT index, MAX(timestamp) AS maxTS FROM table GROUP BY index; CREATE VIEW NewestList AS SELECT * FROM table AS t JOIN NewestTimestamps sub ON t.timestamp = sub.maxTS AND sub.index = t.index WHERE t.total = (SELECT t2.total FROM table AS t2 WHERE timestamp = (SELECT MAX(timestamp) FROM table) );
这个列表并不是我要求的,但实际上似乎无法可靠地区分新旧数据。相反,这将为我提供索引1处的最新元素,然后是索引2等...此外,WHERE子句将视图的大小限制为最近到达的队列的大小。
请注意,第一个视图是必需的,因为mysql不允许视图中FROM子句中的子查询。