SQL:需要基于子查询限制resultset

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 |

我遇到了一个相当奇怪的问题。我可以在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示例我建议的查询:

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