0

私はsql-expertではありませんが、この問題に遭遇しました:

MicrosoftSQL2008サーバーからデータを取得する必要があります。記録間隔のない、さまざまなプローブからのさまざまな測定データを保持します。つまり、一部のプローブはデータベース内のデータを週に1回、別のプローブは1秒に1回転送できます。プローブはID(一意ではない)によって識別され、ポイントは各ID(プローブ)から最後のレコードのみを取得することです。テーブルは次のようになります(最後の5、SampleDateTimeの説明による順序):

TagID   SampleDateTime  SampleValue     QualityID
13      634720670797944946      112     192
23      634720670797944946      38.1    192
17      634720670797944946      107.5   192
14      634720670748012090      110.6   192
19      634720670748012090      99.7    192

サーバーや設定を変更することはできません。クエリを実行することのみが許可されています。そして、要求されたデータを等間隔で(たとえば、1分に1回程度)取得する必要があります。100を超えるプローブ(異なるIDを持つ)があり、そのうち約40を読み取る必要があります。したがって、これを単一のクエリで実行できる場合は、各行を個別のクエリで取得するよりもはるかに効率的である可能性があると思います。

MySQLと同様のテーブルを使用すると、この方法で望ましい結果が得られました(より良い方法の提案が高く評価されています!):

SELECT TagID,SampleDateTime,SampleValue FROM 
(
    SELECT TagID,SampleDateTime,SampleValue FROM measurements 
    WHERE TagID IN(101,102,103) ORDER BY SampleDateTime DESC
) 
AS table1 GROUP BY TagID;

正しいデータでも、それでうまくいくと思いました(MAX()やDISTINCTで管理できなかった、または何を試しても)。ただし、「GROUP BY」が原因で、MsSQLでは当然機能しません。

Column 'table1.SampleValue' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

私はこれに非常に固執しているので、どんな洞察も大歓迎です。

4

1 に答える 1

1

MySQLとSQL-Serverにタグを付けているので、少し混乱しています。SQL-Serverの場合、次のROW_NUMBER機能を使用して支援します。

SELECT  m.TagID, m.SampleDateTime, m.SampleValue, m.QualityID
FROM    (   SELECT  *, ROW_NUMBER() OVER(PARTITION BY TagID ORDER BY SampleDateTime DESC) [RowNumber]
            FROM    Measurements 
        ) m
WHERE   Rownumber = 1

このROW_NUMBER関数は、缶に書かれていることを正確に実行し、指定した基準に基づいて各行に番号を付けます。したがって、上記の例では、新しいTagIDが検出されるたびに1から再開するようにPARTITION BY TagID指示されています。最新のエントリで各TagIDの番号付けを開始し、最初のエントリまで上に向かって作業するように指示します。ROW_NUMBERORDER BY SampleDateTime DESCROW_NUMBER

クエリが失敗した理由は、MySQLが暗黙のgroup byを許可しているためです。つまりGROUP BY TagID、選択リストにあり、集計関数に含まれていないフィールドのみを指定したため、それらに割り当てられた「ランダム」行の値が取得されます(ORDER BY SampleDateTime DESCサブクエリで指定したため、ケースの最新の行。

必要な場合に備えて、ほとんどのDBMSで以下が機能するはずであり、MySQLで実行しているクエリと同様のクエリを生成するためのより良い方法です。

SELECT  m.TagID, m.SampleDateTime, m.SampleValue, m.QualityID
FROM    Measurements m
        INNER JOIN
        (   SELECT  TagID, MAX(SampleDateTime) AS SampleDateTime
            FROM    Measurements
            GROUP BY TagID
        ) MaxTag
            ON MaxTag.TagID = m.TagID
            AND MaxTag.SampleDateTime = m.SampleDateTime
于 2012-05-08T11:10:51.033 に答える