2

レコードでいっぱいのタイムスタンプ列を持つテーブルがあり、1 つのクエリのみを使用して、2 つの連続するレコード間の最小時間差を計算したいとします。

みたいなテーブルかも…

CREATE TABLE `temperatures` (
  `temperature` double,
  `time` timestamp DEFAULT CURRENT_TIMESTAMP
);
4

4 に答える 4

4

必要なのは、分析関数LAGMIN.

にはありませんがMySQL、セッション変数を使用して簡単にエミュレートできます。

このクエリは、連続するレコード間のすべての違いを返します。

SELECT  (temperature - @r) AS diff,
        @r := temperature
FROM    (
        SELECT  @r := 0
        ) vars,
        temperatures
ORDER BY
        time

これは最小の時差を返します:

SELECT  (
        SELECT  id,
                @m := LEAST(@m, TIMEDIFF(time, @r)) AS mindiff,
                @r := time
        FROM    (
                SELECT  @m := INTERVAL 100 YEAR,
                        @r := NULL
                ) vars,
                temperatures
        ORDER BY
                time, id
        ) qo
WHERE   qo.id = 
        (
        SELECT  id
        FROM    temperatures
        ORDER BY
                time DESC, id DESC
        LIMIT 1
        )

で分析関数をエミュレートする方法については、私のブログのこの記事を参照してくださいMySQL

テーブルに a を追加する場合PRIMARY KEY(常に行う必要があります)、より多くのSQL-ish ソリューションを使用できます。

SELECT  temperature -
        (
        SELECT temperature
        FROM   temperatures ti
        WHERE  (ti.timestamp, ti.id) < (to.timestamp, to.id)
        ORDER BY
               ti.timestamp DESC, ti.id DESC
        LIMIT 1
        )
FROM    temperatures to
ORDER BY
       to.timestamp, to.id

ただし、このソリューションは、バグ 20111MySQLのために非常に非効率的です。

サブクエリはアクセス パスを使用しませんが、順序付けには ( 、 )rangeのインデックスを使用します。timestampid

UDFこれは、現在のレコードの を指定して、以前の温度を返すを作成することで回避できますid

詳細については、私のブログのこの記事を参照してください。

フィルタリング条件を使用しない場合は、セッション変数を使用するソリューションが最も効率的ですが、MySQL具体的です。

同様のソリューションは次のSQL Serverようになります。

SELECT  temperature -
        (
        SELECT TOP 1 temperature
        FROM   temperatures ti
        WHERE  ti.timestamp < to.timestamp
               OR (ti.timestamp = to.timestamp AND ti.id < to.id)
        ORDER BY
               ti.timestamp DESC, ti.id DESC
        )
FROM    temperatures to
ORDER BY
       to.timestamp, to.id

SELECT  MIN(mindiff)
FROM    (
        SELECT  timestamp -
                (
                SELECT TOP 1 timestamp
                FROM   temperatures ti
                WHERE  ti.timestamp < to.timestamp
                       OR (ti.timestamp = to.timestamp AND ti.id < to.id)
                ORDER BY
                       ti.timestamp DESC, ti.id DESC
                ) AS mindiff
        FROM    temperatures to
        ORDER BY
               to.timestamp, to.id
        ) q

ではSQL Server、インデックスが にある場合(timestamp, id)(またはがクラスター化され(timestamp)ている場合は にある場合)、これは問題なく機能します。PRIMARY KEY

于 2009-05-23T12:24:34.743 に答える
3

タイム スタンプに一意の制約があると仮定します (同時に 2 つの録音が行われないようにするため)。

SELECT MIN(timediff(t1.`time`, t2.`time`)) AS delta_t,
    FROM temperatures t1 JOIN temperatures t2 ON t1.`time` < t2.`time`

これはかなり正確に質問に答えますが、他の有用な情報 (2 つのタイムスタンプや温度など) は伝えません。

于 2009-05-23T17:10:59.660 に答える
2

次のようなクエリを試してください。

select 
    cur.timestamp as CurrentTime,
    prev.timestamp as PreviousTime,
    timediff(cur.timestamp,prev.timestamp) as TimeDifference,
    cur.temperature - prev.temperature as TemperatureDifference
from temperatures cur
left join temperatures prev on prev.timestamp < cur.timestamp
left join temperatures inbetween
    on prev.timestamp < inbetween.timestamp
    and inbetween.timestamp < cur.timestamp
where inbetween.timestamp is null

最初の結合は、現在の ("cur") 行の前のすべての行を探します。2 番目の結合は、最初の行と 2 番目の行の間の行を探します。where ステートメントは、最初の行と 2 番目の行の間に行が存在できないことを示しています。そうすれば、前の行を含む行のリストを取得できます。

于 2009-05-23T08:49:53.303 に答える
0

これを試すことができます:

SELECT
    T1.*,
    (SELECT MIN(T2.time)
     FROM temperatures T2
     WHERE T2.time > T1.time)-T1.time diff
FROM
    temperatures T1
ORDER BY
    T1.time
于 2009-05-23T08:48:25.223 に答える