web-dev-qa-db-ja.com

クエリ結果からサブセットを選択する方法

次の行と前の行の間の時間差と距離を計算するクエリがあります。

SELECT  * FROM (
            SELECT 
                iVehicleMonitoringId AS PreviousId,
                LEAD(iVehicleMonitoringId, 1) OVER (PARTITION BY iAssetID ORDER BY dtUTCDateTime) AS CurrentId, 
                iGeofenceId AS GeofenceId,
                eEventCode as 'EventCode',
                iAssetId AS AssetId,
                LEAD(iAssetId, 1) OVER (PARTITION BY iAssetID ORDER BY dtUTCDateTime) AS PreviousAsset,
                sDigitalInputValue AS PreviousIgnition,
                LEAD(sDigitalInputValue, 1) OVER (PARTITION BY iAssetID ORDER BY dtUTCDateTime) AS CurrentIgnition,
                dtUTCDateTime AS StartDate,
                LEAD(dtUTCDateTime, 1) OVER (PARTITION BY iAssetID ORDER BY dtUTCDateTime) AS EndDate,
                DATEDIFF(second, dtUTCDateTime, LEAD(dtUTCDateTime, 1) OVER (PARTITION BY iAssetID ORDER BY dtUTCDateTime)) AS DateDiffSeconds,
                sptGeoLocaitonPoint.STDistance(LEAD(sptGeoLocaitonPoint, 1) OVER (PARTITION BY iAssetID ORDER BY dtUTCDateTime)) AS Distance

                FROM VehicleMonitoringLog
                    WHERE dtUTCDateTime > @utcStartDate AND dtUTCDateTime < @utcEndDate
                            AND iAssetId in (Select iAssetID From #tblAssets)
        ) AS dt
        ORDER BY dt.AssetId, dt.StartDate

次の結果を返します

enter image description here

これで問題ありません。選択したセクション間の合計距離と時間を計算する必要があります(青色で強調表示)。

つまり、基本的には、eEventCode = 6からeEventCode = 7までの合計距離と合計時間です。開始イベント= 6と終了イベント= 7のセットが複数存在する場合があります。

SQLフィドル

この操作を実行するにはどうすればよいですか?

[〜#〜] edit [〜#〜]さて、これはデータセットを持つ新しいフィドルです: http://sqlfiddle.com /#!6/40a9e1

このデータには、開始イベントコード= 6と終了イベントコード= 7の2つのデータセットがあります。

enter image description here

次に、このクエリを実行すると、2つの隣接するポイント間の距離を取得できます。

SELECT 
    iVehicleMonitoringId AS PreviousId,
    LEAD(iVehicleMonitoringId, 1) OVER (PARTITION BY iAssetID ORDER BY dtUTCDateTime) AS CurrentId, 
    iGeofenceId AS GeofenceId,
    iAssetId,
    dtUTCDateTime,
    eEventCode as 'EventCode',
    DATEDIFF(second, dtUTCDateTime, LEAD(dtUTCDateTime, 1) OVER (PARTITION BY iAssetID ORDER BY dtUTCDateTime)) AS DateDiffSeconds,
    sptGeoLocaitonPoint.STDistance(LEAD(sptGeoLocaitonPoint, 1) OVER (PARTITION BY iAssetID ORDER BY dtUTCDateTime)) AS Distance

    FROM VehicleMonitoringLog
        WHERE 
        iAssetId = 6024 AND
        dtUTCDateTime > N'2016-01-26 04:44:00' AND dtUTCDateTime <  N'2016-01-26 12:39:45'
        Order by dtUTCDateTime

結果として、各セットのすべての距離列が追加されます。

enter image description here

2
Dawood Awan

このクエリは、6から7までのすべての距離を合計します。

SELECT AssetId, [Event], GeofenceId
    , DistanceCoveredK = SUM(DistanceCoveredK)
    , TimeSpentDuringVisitSeconds
FROM (
    SELECT AssetId = vm.iAssetId
        , [Event] = c.eEventCode
        , DistanceCoveredK = p.sptGeoLocaitonPoint.STDistance(
            LEAD(p.sptGeoLocaitonPoint) OVER(PARTITION BY vm.iAssetId, vM.dtUTCDateTime ORDER BY c.dtUTCDateTime)
        )
        , GeofenceId = vm.iGeofenceId
        , TimeSpentDuringVisitSeconds = DATEDIFF(SECOND, vm.dtUTCDateTime, c.dtUTCDateTime)
    FROM VehicleMonitoringLog vm
    CROSS APPLY (
        SELECT top(1) eEventCode, dtUTCDateTime, sptGeoLocaitonPoint 
        FROM VehicleMonitoringLog WHERE iAssetId = vm.iAssetId AND dtUTCDateTime > vm.dtUTCDateTime AND eEventCode = 7
        ORDER by dtUTCDateTime
    ) c
    INNER JOIN VehicleMonitoringLog p ON p.iAssetId = vm.iAssetId AND p.dtUTCDateTime >= vm.dtUTCDateTime AND p.dtUTCDateTime <= c.dtUTCDateTime
    WHERE vm.eEventCode = 6
) g
GROUP BY AssetId, [Event], GeofenceId, TimeSpentDuringVisitSeconds

出力:

AssetId Event   GeofenceId  DistanceCoveredK    TimeSpentDuringVisitSeconds
6024    7       1015        172,642601234594    100
6024    7       1015        1210,11662866215    28393

SQLのsptGeoLocaitonPointのデータ型をFiddleからintからgeographyに変更しました。新しいSQL Fiddle = is here

2