|
我需要确定在给定的日期范围内每辆汽车某条路线行驶了多少次,但是基于数据库的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()) |
|