1

私はかなり奇妙な問題に遭遇しました。mysql データベースで使用する次のサンプル データがあります。

    |キー| データ| インデックス | 合計 | タイムスタンプ |
    | | # | | | 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 |
    | | * | | ふ | 1 | 2 | 2009-01-05 01:01:32 |

何が起こっているかというと、別のプロセス (私の制御下にない) がデータ パケットを受信し、それらを到着時刻のタイムスタンプと共にデータベースに直接格納しています。パケットはバーストで到着するはずです... a、bは互いに近くに到着し、インデックス1と2が付けられ、各パケットには送信されたパケットの「合計」数が含まれます。key は通常の自動増分主キーです。

私が必要としているのは、到着した最新のリストを表示するビューです (すべてのパケットが到着していない場合、部分的なリストは許容されます)。

上記のクエリの場合、結果は理想的には「f」のみになるはずですが、それを行う方法がわかりません。別の方法で取得できない場合は、"a" と "f" を返すこともできます。つまり、select ステートメントによって捕捉される少量の余分なデータは大きな問題ではありません。「f」が到着する前の期間の正しい戻り値は、c、d、および e です。

私の一般的な考えは、次のようなものです。

SELECT * FROM テーブル WHERE 合計 = (
    SELECT 合計 FROM テーブル WHERE タイムスタンプ = (
        SELECT MAX(タイムスタンプ) FROM テーブル
    )
)
ORDER BY DESC タイムスタンプ
リミット (
    SELECT 合計 FROM テーブル WHERE タイムスタンプ = (
        SELECT MAX(タイムスタンプ) FROM テーブル
)

お気づきの方もいらっしゃると思いますが、LIMIT 句でサブクエリを実行することはできません (少なくとも mysql では)。誰かがこの問題を解決するための別のアプローチを持っていますか? 上記のクエリは、最近の ID の小さなリストに JOIN をネストすることでより明確にすることができますが、それでもサブクエリに LIMIT サブクエリの問題が残ります。

2 段階のクエリであるため、これは比較的簡単です。問題は、それが VIEW の選択ステートメントを定義する必要があることです。

間違ったSQLの例を修正するために編集

4

4 に答える 4

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>
于 2009-03-04T21:13:44.763 に答える
0

これは、SQLサーバーで行う方法です。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)
于 2009-03-04T21:21:25.290 に答える
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
于 2009-03-04T21:15:54.990 に答える