回答

收藏

如何使用SQL计算路线经过的次数?

技术问答 技术问答 268 人阅读 | 0 人回复 | 2023-09-14

我需要确定在给定的日期范围内每辆汽车某条路线行驶了多少次,但是基于数据库的GPS管理软件没有此功能。
) R4 \- {) m0 |, k7 Y* M该数据库包含几个表,这些表存储GPS,路线和位置数据。一条路线由几个位置和一个序列号组成。位置是一组附加在名称上的上下界纬度/经度值。车辆每分钟几次将其GPS位置数据上载到服务器,服务器会更新GPS表。
+ p5 I# r6 t; [3 N例如。某个路线“ FOO”可以依次包括位置“仓库”,“学校”,“体育场”和“公园”。“. T% G- b, f7 r! a6 J! A5 r1 C
BAR”本质上是同一条路线,但方向相反(可能在几条不同的路线上找到位置)。
) U% p( o- v& V0 L: E一个简单的选择即可从GPS数据表中返回此类信息(车辆ID,位置,日期时间):7 g1 t  |. Z5 c- J1 m
34  Warehouse  2011-03-26 18:17:50.000
. i- A5 V+ v9 Q( {- Z; C34  Warehouse  2011-03-26 18:18:30.000' W% r9 p% y7 V
34  Warehouse  2011-03-26 18:19:05.000" j1 o6 b& n) o0 ^9 x1 G/ a
34  School     2011-03-26 18:21:34.000
  t" y7 s6 u# x  \# }- E34  School     2011-03-26 18:21:59.000* K0 D8 {9 n8 x) b
34  School     2011-03-26 18:22:42.000# H# J5 \8 |2 T9 D. K
34  School     2011-03-26 18:23:55.000, R7 x- A) s% M$ i, P  Q8 ?
34  Stadium    2011-03-26 18:24:20.000
7 Z" L9 u/ n4 |- J$ S. K34  Stadium    2011-03-26 18:24:47.000
. ?* g8 R/ I/ \8 m34  Park       2011-03-26 18:25:30.000' ~3 U' C- Y- H/ x2 t
34  Park       2011-03-26 18:26:50.0001 N; L+ l& q7 \: @3 U7 C6 M  ^
34  Warehouse  2011-03-26 18:28:50.000
' ~4 f, H, ^2 a/ N3 v' w+ x等等。
4 x6 X/ a- o' `& i: J4 @1 v1 D9 R从手动检查中可以明显看出,车辆34当天至少走过“?? FOO”路线。如何使用SQL确定当天每辆车经过该路线的总次数?
; K& o; a  k+ S我感觉到我将不得不使用某种控制中断结构,但我希望有一种更简单的方法。这是用于从GPS表检索信息的SQL。% A  {1 d0 C# Z3 F" u$ `( m
SELECT
& p6 b5 a8 e# ]0 d# h    v.VehicleID,
+ ?, \3 e1 J- m    ml.LocationName( C- ~6 y3 u# \. u& `( d( b7 K
    gps.Time,5 k/ H" ?8 v1 O8 ]+ m8 Q
FROM dbo.Routes r 8 ?6 e6 Q0 ]+ F
INNER JOIN dbo.RoutePoints rp
9 _3 @6 K/ n4 Y& f        ON r.RouteId = rp.RouteId
1 l( U9 Q- p. a" cINNER JOIN dbo.MapLocations ml
& @  x- I% H1 t1 `3 Y        ON rp.LocationId = ml.LocationId, s% U* X5 h3 O
INNER JOIN dbo.GPSData gps 6 B5 G8 o+ m! b- ?
        ON ml.LowerRightLatitude   gps.Latitude
# c% s8 }' {0 l( [7 \$ O        AND ml.UpperLeftLongitude  gps.Longitude5 L+ N* a, }: t8 o
INNER JOIN dbo.Vehicles v 2 V) W6 w9 S$ I' y
        ON gps.VehicleID = v.VehicleID $ M' Z+ L# k$ f( V) |8 i
WHERE   r.Desc = @routename
& ?4 `3 c, G4 ?# H% n/ t/ I, VAND gps.Time BETWEEN @startTime AND @endTime3 m+ f; ^/ S$ U7 F- \
ORDER BY v.VehicleId, gps.Time
% T* M' I& o  {( _% j. O编辑:回溯不被视为同一路线的一部分。 仓库,学校,体育场,公园仓库,学校,体育场,公园 。FOO路线只有两次旅行。如果某个位置的偏离不属于+ J: O6 f( q* r& A
已知路线, 例如 仓库,学校,体育场,酒吧,公园 ,则可以忽略该位置。(即,仍然将其视为路线“ FOO”); u# }3 L0 B% ^9 J9 Q
                - h- b4 S$ o. }, \# s2 O' g( k
解决方案:
1 z* t8 Y& J# p3 r# w               
& t# K- ^; K1 `3 u" J1 _( T  Z
. b+ I8 t0 |! _% S8 ~' H
: j' z/ d2 z6 B) h& n7 r, X                DECLARE @route
" I+ _7 n* J0 T' K7 Z6 v+ A! f        TABLE3 O5 \/ r) C: \# K
        (# r* _5 D8 U8 {8 x( O3 H& N1 J; l- q& y
        route INT NOT NULL,
6 \* y9 w3 d1 ^& j        step INT NOT NULL,
) P! F3 W3 Q4 m! t9 Z        destination INT NOT NULL,  \# K2 [; J) y. ?) m
        PRIMARY KEY (route, step)
8 c7 l; e2 x. }% j0 h% U        )9 G; p8 ]9 F! t/ N$ X8 J" e) y6 p. V
INSERT
* J% t1 f# ~$ s: _& xINTO    @route
. a; b" e, M, MVALUES
/ }+ b9 S6 ^' C- B+ @: k3 d        (1, 1, 1),0 o" H. @" L1 Q
        (1, 2, 2),3 |8 {8 r& v" N9 W+ J: V
        (1, 3, 3),1 _  u* A6 ?0 G$ [+ X$ M
        (1, 4, 4),
6 p% A. I8 }4 m$ G( d4 k        (2, 1, 3),
( R1 w; h' l, x/ |' k* v        (2, 2, 4)
4 I$ Z$ c% ?; Z& u% W% P4 UDECLARE @gps6 |) Q( J1 }: q* S- {
        TABLE
8 a3 ~- V0 r) m" {$ k  @: ]        (0 B' U: n/ p, @- M% `7 \  R
        vehicle INT NOT NULL," Z& f1 F3 F$ L$ E& Y; C
        destination INT NOT NULL,
6 t6 k# r) \+ W- J' L        ts DATETIME NOT NULL
1 _1 z, D7 n" C. S( R        )
; n) D0 Z# o; gINSERT' Y2 W6 f- s9 O5 F+ P
INTO    @gps: r  s  o6 w6 _; `7 H& R
VALUES4 E; n  n( S! p: |) S
        (1, 1, '2011-03-30 00:00:00'),6 d1 W$ P! U/ s& G1 c; e/ J
        (1, 2, '2011-03-30 00:00:01'),  j6 z( W* c7 p0 ~$ A, o* Y
        (1, 1, '2011-03-30 00:00:02'),
5 F' \4 ?" U" ^# J        (1, 3, '2011-03-30 00:00:03'),+ m# W9 h0 m1 f1 F3 ~& F! I7 \5 l
        (1, 3, '2011-03-30 00:00:04'),& E( j# g0 h" ~0 v# v8 F6 J, B
        (1, 3, '2011-03-30 00:00:05'),: ?( p/ A, e6 [- |
        (1, 4, '2011-03-30 00:00:06'),3 D/ c8 q! S- M1 H3 Q2 @& p) P
        (1, 1, '2011-03-30 00:00:07'),
$ t) P( o( {7 S( H; }3 G        (1, 3, '2011-03-30 00:00:08'),5 k* C6 D9 S2 D$ I
        (1, 4, '2011-03-30 00:00:09'),
! ~8 @- \; }2 ^* R* K5 A        (1, 1, '2011-03-30 00:00:10'),
$ w- V4 z4 Q  e7 y1 ^        (1, 2, '2011-03-30 00:00:11'),! K5 {' Q. \* R7 @' }+ ~6 J" v
        (1, 2, '2011-03-30 00:00:12'),, n# h+ a2 x3 q3 }( c
        (1, 3, '2011-03-30 00:00:13'),
! l, A- C# i% Q# Z( \; X9 @        (1, 3, '2011-03-30 00:00:14'),
# ]  v8 E8 t/ c& f' T        (1, 4, '2011-03-30 00:00:15'),, ]$ n2 c6 d; G/ L3 q4 q
        (1, 3, '2011-03-30 00:00:16'),
& g# _" t+ d2 e& b        (1, 4, '2011-03-30 00:00:17')
, }6 w4 U& _( B% y# Q( e# f! ^;. m' |" V- ~# n( {4 J' L
WITH    iteration (vehicle, destination, ts, route, edge, step, cnt) AS1 H3 {6 r0 l* d
        (
5 B' T+ t7 _" `$ ^# c        SELECT  vehicle, destination, ts, route, 1, step, cnt
3 w. T" {7 P$ V5 v8 E) s/ Q        FROM    (
- l% o) }& {, z. J, \                SELECT  g.vehicle, r.destination, ts, route, step, cnt,1 W* B! u, G9 T, c0 X1 ^
                        ROW_NUMBER() OVER (PARTITION BY route, vehicle ORDER BY ts) rn7 `$ H4 {2 b& a5 K
                FROM    (% Q8 ?; I& J$ x1 j" L% s* ~4 N
                        SELECT  *, COUNT(*) OVER (PARTITION BY route) cnt0 K8 t' t0 q3 z0 T; t2 s; p
                        FROM    @route
4 t( V  R4 N% N# F7 i                        ) r4 z$ Y* U$ h) Z1 A: q6 E- Z* e% Z  g
                JOIN    @gps g6 r9 j- |. l( V, n9 U9 J9 k1 h
                ON      g.destination = r.destination/ S( X! `  G" A/ @! z
                WHERE   r.step = 1/ L3 Y, U3 P  n
                ) q7 ?& V; k* n/ P
        WHERE   rn = 1
6 M9 z8 Z9 N6 I% M* f        UNION ALL
. U; i& B, v+ A        SELECT  vehicle, destination, ts, route, edge, step, cnt5 m4 ^) _2 L3 j& Z! b0 `3 Y
        FROM    (/ b8 I5 _* U2 Y: @
                SELECT  i.vehicle, r.destination, g.ts, i.route, edge + 1 AS edge, r.step, cnt,8 w3 x6 ]4 W. u  e( j6 l
                        ROW_NUMBER() OVER (PARTITION BY i.route, g.vehicle ORDER BY g.ts) rn2 W3 A" z( d# V8 ^# v5 t
                FROM    iteration i- g7 D& J5 d6 N  r# K% ~( I: a
                JOIN    @route r, s8 |. U* O% l1 F
                ON      r.route = i.route
/ i- Z# V' |- Q) O1 ~; f" E                        AND r.step = (i.step % cnt) + 1
. d/ B+ q1 D! G5 |                JOIN    @gps g: ?; P" ?( R6 m
                ON      g.vehicle = i.vehicle
+ b& D3 B& U( _% h6 u                        AND g.destination = r.destination- d$ f3 O. h, m3 \
                        AND g.ts > i.ts
1 C- V/ W% _- [9 d. |$ }  _" k) i* y                ) q
- b" z* Y" b2 B: J' w+ q4 T8 A% L        WHERE   rn = 1
1 a' M9 ?" Y  m        )
# I+ `; c( n/ l# I/ dSELECT  route, vehicle, MAX(edge / cnt)3 `9 R+ d% q7 P9 B
FROM    iteration+ V7 v0 m/ |0 e; ^1 F8 J3 H, a
GROUP BY
! r' b9 l9 L( h5 Y- P! n        route, vehicle
; u# Q  x# `/ M) k$ Y. T" D在这里,我们有两条路线:(1, 2, 3, 4)和(3, 4)
6 `" N1 Q5 l0 g  Y% w# Z车辆在途中行驶了2次,在途中行驶了(1, 2, 3, 4)4次(3, 4)。4 {& w( Q" l$ m! Z0 O
重要的是,每个路由具有编号从开始的步骤1和无间隙(虽然如果不是的话,你可以很容易地解决它使用附加CTE有ROW_NUMBER())
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则