SQL:需要基于子查询限制resultset
我遇到了一个相当奇怪的问题。我可以在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,每个数据包包含传输的数据包总数。键是一个正常的自动递增主键 我需要的是一个视图,它将显示已到达的最新列表。如果不是所有数据包都已到达,则部分列表是可接受的 对于上面的查询,理想情况下结果应该是f,但我没有看到这样做的方法。如果我们不能用另一种方法得到它,返回a和f是可以接受的。换句话说,select语句捕获的少量额外数据并不是什么大问题。在fs到达之前的一段时间内,正确的返回值为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 ) 正如你们中的一些人可能已经注意到的,至少在mysql中不能在LIMIT子句中执行子查询。有人有其他方法来解决这个问题吗?通过将一个连接嵌套到一个最近id的小列表中,可以使上面的查询更加清晰,但这仍然会在子查询中留下限制子查询的问题 作为一个两阶段的查询,这是相对简单的。问题是它需要成为视图的定义select语句 编辑以修复错误的sql示例我建议的查询:SQL:需要基于子查询限制resultset,sql,mysql,subquery,Sql,Mysql,Subquery,我遇到了一个相当奇怪的问题。我可以在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 |
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>
我的建议是:
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>
如果它们是按顺序到达的,而中间没有写入其他数据包,那么下面的代码也应该起作用
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
如果它们是按顺序到达的,而中间没有写入其他数据包,那么下面的代码也应该起作用
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
这就是我在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)
这就是我在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)
我最终使用了一个稍微不同的查询表单: 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子句中进行子查询。我最终使用了一个稍微不同的查询表单: 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子句中使用子查询。您能否尝试清楚地解释什么是最新的?因为你说F和A是可以接受的,所以它看起来不像是直接的时间戳。我假设一种方法,你可以保证唯一的索引值,确保返回的行数不超过总行数。基本上说,虽然f的返回非常关键,但返回a也不是致命的缺陷。遗憾的是,每个集合都没有标识符,如果您的集合跨越2天,或者两个集合重叠,您将遇到麻烦。因为索引是按顺序分配的,你可以用我下面的答案。。。。或者我在下面所做的,任何一个都应该有效。你能尝试清楚地解释什么是最新的吗?因为你说F和A是可以接受的,所以它看起来不像是直接的时间戳。我假设一种方法,你可以保证唯一的索引值,确保返回的行数不超过总行数。基本上说,虽然f的返回非常关键,但返回a也不是致命的缺陷。遗憾的是,每个集合都没有标识符,如果您的集合跨越2天,或者两个集合重叠,您将遇到麻烦。因为索引是按顺序分配的,你可以用我下面的答案。。。。或者我在下面做的那个,两个都可以。不。。。但我明白为什么这个问题令人困惑。。。编辑以添加fs到达之前的时间段,正确的返回值为c、d和e。请注意,在f到达之前,只返回d,因为只有d的时间戳匹配。数据包不是按顺序到达的,也不是一次全部到达的。。所以我在想,如果它们按顺序到达,就获取最高的索引1,因为你的准时率较低,数据包序列的总数也较低。不。。。但我明白为什么这个问题令人困惑。。。编辑以添加fs到达之前的时间段,t
正确的返回值是c、d和e。注意,在f到达之前,它只返回d,因为只有d的时间戳匹配。数据包不是按顺序到达的,也不是一次全部到达的。。所以我在想,如果它们按顺序到达,获取最高的索引1,因为你的时间下限和数据包序列的总数。我可能会采用这样的方法。不幸的是,有时这些时间戳会彼此相差几个小时。好奇的是,这是使用非常断断续续的管道的遥感科学数据。@kiruwa,如果是这样的话,你就不能可靠地构造一个查询来获取上次传输的所有数据。如果两个总数相同的传输在两个数据包之间间隔数小时到达,那么你就注定了。。。命中注定我说是的,尝试只是为了接近些什么。两阶段查询的等价物:foo=selecttotal FROM表,其中timestamp=selectmaxtimstamp。。。从表中选择*,其中total=$foo ORDER BY DESC timestamp LIMIT fooI可能会采用如下方法。不幸的是,有时这些时间戳会彼此相差几个小时。好奇的是,这是使用非常断断续续的管道的遥感科学数据。@kiruwa,如果是这样的话,你就不能可靠地构造一个查询来获取上次传输的所有数据。如果两个总数相同的传输在两个数据包之间间隔数小时到达,那么你就注定了。。。命中注定我说是的,尝试只是为了接近些什么。两阶段查询的等价物:foo=selecttotal FROM表,其中timestamp=selectmaxtimstamp。。。从表中选择*,其中total=$foo ORDER BY DESC timestamp LIMIT foo