|
对于这个例子说,我有两个字段的表,AREA varchar(30)和OrderNumber INT。
* M- k. p8 S& o1 _" h6 q该表具有以下数据, V! t" p( ]3 w' e# y4 a
AREA | OrderNumber" S; R* S m% l* e0 e r
Fontana | 326 [) {1 S* D+ Q
Fontana | 428 [; u r! V6 v' m; l- D
Fontana | 76
5 r6 U- g* v+ h) n2 g* a" {% sFontana | 12
+ p" a' g) b6 `4 r6 wFontana | 3# B/ x7 N6 w+ L6 l
Fontana | 99 e4 u: ~6 f0 _* p: ?1 M
RC | 32 v7 W' @& R4 x4 Q" E3 B6 M
RC | 1
2 b& R0 M. m0 {. X& v S! K$ hRC | 8
& A7 N6 p$ u- t- T; s, DRC | 98 r2 a* V& h6 ~" V
RC | 4
3 b( Q+ J9 ]2 z) c# w) \我想回来
: l8 J$ v& i. F5 F$ B我想返回的结果是每个区域递增连续值的最长长度。对于Fontana it is 3 (32, 42, 76)。For RC it is 2 (8,9)
( q# ?" V0 u) D7 @' aAREA | LongestLength
. T& V5 Q" p3 AFontana | 31 Q. @7 G! [* T7 `7 z, ~
RC | 2
, F, e- p! L, X' ]/ ^我将如何在MS Sql 2005上执行此操作?
( O& k7 b2 ~2 D& y- W; y& U ; ~" g$ G- Z! w$ c+ q
解决方案:6 p1 ]. a( _. F/ s" C# A
9 x: h9 ]% q6 H0 Z H
7 f" \5 m& d: h, S# \! u
3 s% T# C1 `: }6 b5 [. ~- e3 _5 r+ { 一种方法是使用遍历每一行的递归CTE。如果该行符合条件(增加同一区域的订单号),则将链长增加一。如果没有,则启动一个新链:7 S4 Q9 l5 j# p, U. ^" H
; with numbered as. C) i' T3 I5 u1 r! v
(
6 q) h. w$ E3 v1 l select row_number() over (order by area, eventtime) rn2 b$ m5 T5 f$ {- H
, *
2 n5 k- E- M4 w/ r5 p' p6 v: B from Table12 B6 M2 x! f3 O# F2 f
)
( L: h2 r7 P# O1 c" Y4 z, recurse as4 i- y8 o( Z' ?! G2 f: J
(
" N/ O& h& g$ M5 T select rn
; ^5 T, R6 ~' Z1 U1 `% ^& K( p , area! u$ ~2 J& C- l y2 ^4 \
, OrderNumber
" z& Y& ?0 |# U& n+ l , 1 as ChainLength
$ V2 e& x4 ^, [9 j from numbered, `4 K& X8 `+ |! _# }. K5 U/ S
where rn = 1$ s' \- K J7 } T2 l" @
union all) p) x5 G1 H- D6 n; V" @
select cur.rn d3 _6 c) v8 j3 F
, cur.area
' p9 Q9 w ~, n4 |8 d) _ , cur.OrderNumber* |, z3 ]3 Y" d) x
, case
/ g* T Q( s0 Z+ z7 U5 o when cur.area = prev.area 5 F* j/ R g* Q: [
and cur.OrderNumber > prev.OrderNumber $ z+ O+ r- R: |' E
then prev.ChainLength + 1 G' r) o/ F3 ] g/ v+ x# `, [
else 13 F9 E. K# o5 f! ^) r
end# G3 J9 l n' W3 a, D# e) ?
from recurse prev( _/ ^- y2 G! [
join numbered cur
+ {& A; F$ @8 V# M2 J G on prev.rn + 1 = cur.rn
) g9 r' W* g$ T4 k6 R( A9 H) a )
- S- M& r! X3 s$ g1 }5 ]select area
* Z) f% x' }7 M" g3 G" \, c0 h, max(ChainLength); x; L- p( c5 a h5 x, P
from recurse
1 h0 C3 G* E& J2 F) u pgroup by
$ k1 c$ i/ \" p! ?% `* ]5 C$ J area6 K+ W% M, [, u" w" s# y
SQL Fiddle的实时示例。
. F6 p* [, V& t另一种方法是使用查询查找“中断”,即以相同区域的顺序编号递增的序列结束的行。中断之间的行数是长度。
4 k/ l1 n. [7 f# Q1 P7 Q; with numbered as, Q% ^" v r" a6 S8 |4 H2 _
(/ z8 j" k1 e* o1 Q' {
select row_number() over (order by area, eventtime) rn4 T/ O+ O) Q7 o
, *
. C/ D7 e9 u: b6 d3 h4 U+ e' q2 X from Table1 t1' P2 A7 y9 O V0 d) J! W1 e' _' s& \
): w M* A- A$ f" l
-- Select rows that break an increasing chain
8 B9 F9 ?4 E2 h6 B# D$ Q3 f, breaks as3 r% H; a4 M$ f5 _/ q1 Q
(
8 h* \! O9 o$ f: Z select row_number() over (order by cur.rn) rn2
9 ?- A f3 q$ b , cur.rn1 O5 K% W- }' M$ }& W) P
, cur.Area4 R! Z8 s8 V1 h& `& ?% M
from numbered cur
5 y% `& j3 p- D6 S3 w% s/ g7 z left join
o h2 N h! M& M: ]" B# y numbered prev8 T1 L& h0 \! B* v
on cur.rn = prev.rn + 1
) l5 T$ u1 l7 X7 _! Z1 H5 Z0 O$ T where cur.OrderNumber prev.Area
7 d. }5 o4 g5 Q# ?4 d" x! c or prev.Area is null
2 k& d! X) y1 c7 O: z4 B6 C1 a )) o M- w! ?* f( V! z3 q
-- Add a final break after the last row
5 r4 a: K. {2 D% b7 T2 y9 x, breaks2 as! Q, M) O C7 e/ G) i+ [
(! b/ R0 ]8 {2 R4 Z" L9 \
select *8 p$ B/ ]+ ^' h
from breaks* {1 K9 X8 p. O K" I
union all7 Z" U, v" c8 S( y
select count(*) + 1
! l" Z: @0 ~7 H9 f , max(rn) + 1: B% j' h' n# j% s7 ]
, null w0 h1 S$ Q5 w# i+ S
from breaks/ a( W' F+ b* G4 n! \( t6 w
)
# U% B/ Z6 q% qselect series_start.area G+ W# S- ]4 x
, max(series_end.rn - series_start.rn)9 ?. T) S" [/ h* b2 B( b
from breaks2 series_start( u9 H) l5 |6 y2 p" O& M! P9 v
join breaks2 series_end; d0 s$ [/ R G, M
on series_end.rn2 = series_start.rn2 + 1# w1 M D( \) L2 T, Y) p. z) K
group by/ t G4 G. j5 J* @" Y) h/ H
series_start.area
$ K5 F( k( R c+ Z, R# q" j [SQL Fiddle的实时示例。 |
|