回答

收藏

基于来自多行SQL Server的标志的时间总和

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

我很难执行查询之一。我需要根据同一张表中的标志找到点火时间。表格如下
" M! x5 z" {, S7 [UnitId      eventtime               ign
+ D+ M: k& R+ R. O  o----------- ----------------------- -----/ v0 p6 w7 m: O  j
356         2011-05-04 10:41:00.000 1! O9 l9 ^3 [, V
356         2011-05-04 10:42:00.000 1
. K& K, D- A/ W" l& ?, O* b356         2011-05-04 10:43:00.000 1
- k- B& [( h7 s+ z  W/ E. b: A356         2011-05-04 10:45:00.000 1
$ {- W/ g4 Z+ e6 i$ _; Z356         2011-05-04 10:47:00.000 1
4 `3 ?' K# F8 g" v% C, ~9 D. ^356         2011-05-04 10:48:00.000 0! A) ~6 X5 }. V0 ]9 z$ f, [$ M$ e
356         2011-05-04 11:14:00.000 1
: B- H& Q* i0 `3 b$ p1 I356         2011-05-04 11:14:00.000 1
5 f# Z' {8 h3 {7 b9 h- E& Y! c; |356         2011-05-04 11:15:00.000 1. q, \. L  g" H
356         2011-05-04 11:15:00.000 1- L6 i+ l3 H/ d. n. y1 q; b9 q! F
356         2011-05-04 11:15:00.000 15 t0 ]" k# W# w0 g  }# q
356         2011-05-04 11:16:00.000 0. B5 K. z4 f3 l  h( D. ]# r
356         2011-05-04 11:16:00.000 0% `/ D3 z! v$ d! G# P& S) P
356         2011-05-04 11:16:00.000 0
3 s8 h7 N4 C4 |& m356         2011-05-04 14:49:00.000 1  M' Y; {6 F( C: \7 m
356         2011-05-04 14:50:00.000 1" i% u- z1 j5 J& C
356         2011-05-04 14:50:00.000 1
1 X- H0 {2 [& s6 ^* g/ M356         2011-05-04 14:51:00.000 14 @# H+ n8 D5 W& L+ g6 F
356         2011-05-04 14:52:00.000 0
9 E5 ]8 `* L& @9 `4 F6 ~356         2011-05-04 14:52:00.000 0# X0 S9 f4 j: r! ?3 f! }$ Z# a: a
356         2011-05-04 20:52:00.000 0: V& c+ s4 }" L4 v) `" {7 V0 X
在此,Ign标志将确定ignition_on和iginition_off时间。所以上表我们可以得到点火对: H, R' Y4 i$ }8 K/ ]6 t9 Q, `
2011-05-04 10:41:00.000 - 2011-05-04 10:48:00.0004 A) H- V6 m6 R
2011-05-04 11:14:00.000 - 2011-05-04 11:16:00.000) o2 `( X/ B+ {3 i
2011-05-04 14:49:00.000 - 2011-05-04 14:52:00.000
& T7 U! T: X& q9 {7 Y3 O$ _( u9 @因此,从上面的对来看,我可以说我的设备运行了7 + 2 + 3 = 12分钟。我不希望上述结果是对的,仅作为示例。我的目的是得到12分钟的结果。
* Z, |& M' A4 A# d我如何使用单个查询来实现它,现在我正在使用CURSOR循环,但是这件事需要花费更多的时间才能使用多天和多个单元。无论如何,在没有CURSOR的情况下我可以实现它吗?
; _& y* ~! H$ J  g                2 \5 a7 E; a6 d5 _" f
解决方案:; F5 p, R9 j3 c. {2 K
                5 V6 t; R$ k6 ?# l$ u. t% L* `

7 z3 A7 V2 A) S' ?8 S; i- p, f
; @; U* p) w4 e                如果还有其他标准可以区分具有相同ign值的连续事件序列,则可以从每个序列中获取ign=1最早的事件,并将其与相应ign=0序列的最早事件联系起来。
" k$ l5 l' ?. y1 o$ L0 }9 N可以添加这样的标准,如下所示。我将首先发布该解决方案,然后解释其工作原理。7 O$ b+ h, v( \5 j. K$ R- ^
首先,设置:
9 u# ^& P+ M, ?. r+ aDECLARE @atable TABLE (
5 |2 O. @" W% D  Id int IDENTITY,0 q  Q7 W$ Y; ?( {; w' r
  UnitId int,
: X- ?1 W5 n# G4 o7 A2 p( I  eventtime datetime,  b% r5 x9 [: x; a
  ign bit
& |: l* {2 O# j4 R, Y1 [);; |! M0 S3 [# o/ ]2 T0 X7 h0 w- H) d8 n
INSERT INTO @atable (UnitId, eventtime, ign)4 ?1 i/ S/ e) E- f, W( D7 j5 t
SELECT 356, '2011-05-04 10:41:00.000', 1 UNION ALL
# }. E4 P! K" oSELECT 356, '2011-05-04 10:42:00.000', 1 UNION ALL3 `9 @. h5 D2 }# i4 R+ [$ ?
SELECT 356, '2011-05-04 10:43:00.000', 1 UNION ALL
- \# B9 l' f- W' }( ^SELECT 356, '2011-05-04 10:45:00.000', 1 UNION ALL
7 N$ s  B* m, B$ |  YSELECT 356, '2011-05-04 10:47:00.000', 1 UNION ALL
/ W3 |8 I3 r+ {SELECT 356, '2011-05-04 10:48:00.000', 0 UNION ALL
. E/ W. s7 V* m8 l0 jSELECT 356, '2011-05-04 11:14:00.000', 1 UNION ALL& C9 Z0 @1 [7 C  p3 u( n
SELECT 356, '2011-05-04 11:14:00.000', 1 UNION ALL; O& n4 L4 U4 T
SELECT 356, '2011-05-04 11:15:00.000', 1 UNION ALL
, J, M+ @; e5 V+ c  O9 }SELECT 356, '2011-05-04 11:15:00.000', 1 UNION ALL6 K3 j& p5 R) c% K& ^
SELECT 356, '2011-05-04 11:15:00.000', 1 UNION ALL
2 h" v9 y/ H9 H+ K$ w" m! FSELECT 356, '2011-05-04 11:16:00.000', 0 UNION ALL
0 E8 `+ N" \- o2 TSELECT 356, '2011-05-04 11:16:00.000', 0 UNION ALL( |1 i5 m( K6 Y6 b4 |# X
SELECT 356, '2011-05-04 11:16:00.000', 0 UNION ALL
& ~  z: C' ?! h9 p: u; |% ]% ]SELECT 356, '2011-05-04 14:49:00.000', 1 UNION ALL# R8 \: R/ D7 |* ]
SELECT 356, '2011-05-04 14:50:00.000', 1 UNION ALL$ \( }/ U/ Z- U
SELECT 356, '2011-05-04 14:50:00.000', 1 UNION ALL
# w; F) w: f9 O$ @SELECT 356, '2011-05-04 14:51:00.000', 1 UNION ALL
) K2 Y* V$ q# \( Q4 J  `SELECT 356, '2011-05-04 14:52:00.000', 0 UNION ALL% \4 ?7 O& e: Z- L9 ]( s8 z
SELECT 356, '2011-05-04 14:52:00.000', 0 UNION ALL
. R$ ?1 T! ~5 ySELECT 356, '2011-05-04 20:52:00.000', 0;
  r/ X  I& Z0 Q1 L7 p& p# A现在查询:
  s* o6 t6 K) W4 y8 G% P6 TWITH) I" C3 K/ |8 D3 `1 O8 q3 [9 E
marked AS (6 }+ a* k" a: j: ^( z5 ~
  SELECT, _) H4 {& G( k' U1 M
    *,& c4 K4 Y% Y% h5 f' b+ `  B
    Grp = ROW_NUMBER() OVER (PARTITION BY UnitId ORDER BY eventtime) -7 V4 L1 g% E0 y$ ~; g: M. W
     ROW_NUMBER() OVER (PARTITION BY UnitId, ign ORDER BY eventtime)4 y, ?5 ?; f+ p% I$ x
  FROM @atable
6 m* a9 o# m. S( H% t4 H9 h- P),
1 W6 {: }, y/ j9 u: d2 Q) uranked AS (% u* K1 D$ I* w
  SELECT
# n" K" i( z* _2 P6 l    *,
9 A! q# H% W& x5 Q& N/ c5 j9 g  e9 X/ s    seqRank = DENSE_RANK() OVER (PARTITION BY UnitId, ign ORDER BY Grp),+ d; x% S3 I" H0 H
    eventRank = ROW_NUMBER() OVER (PARTITION BY UnitId, ign, Grp ORDER BY eventtime)* a7 g$ d2 J0 b/ ]2 b7 w
  FROM marked
% Q, l# d% q& ~7 O# Q, K. v),/ W! Q0 d# A5 B1 P- M0 D
final AS (1 R( X5 P- N7 o5 O% x' [( u7 i
  SELECT
- D) U& w2 b6 g" Q! T    s.UnitId,8 h0 `; [8 E' c& ?) v" P
    EventStart = s.eventtime,
0 t; {# o* K; j6 i    EventEnd   = e.eventtime
& R5 |/ |& Q9 |. R1 C& U  FROM ranked s
( n' b; }4 _0 `4 m7 p' }: e3 \    INNER JOIN ranked e ON s.UnitId = e.UnitId AND s.seqRank = e.seqRank* `6 @( T) e3 ~' l2 |$ w/ G
  WHERE s.ign = 1
/ t: ~) ?5 u3 S) `. N% k4 R    AND e.ign = 0
: m  O% E* ?( R$ X- l    AND s.eventRank = 1
# ^  {3 j/ Z. d8 b    AND e.eventRank = 1
' {: V! d5 d! L0 x) J5 {6 k* P)8 T# |$ [5 v% P1 {0 h+ J, c
SELECT *
2 f7 o4 O! k# L; s3 V5 [FROM final' n" S( |' v2 B6 U& K& _; y
ORDER BY- S7 \; m0 g& }6 {( L. a. x
  UnitId,) v6 g5 O3 ?  d! m
  EventStart
7 a8 N  M0 _8 \& _: ?% x1 {/ M这就是它的工作方式。
, I% q% |$ G7 u# _. }  i, A在marked公用表表达式(CTE)为我们提供了我说的是在开始的附加标准。它产生的结果集如下所示:/ P7 j. M$ E. a* w" m. T
Id  UnitId  eventtime                ign  Grp6 N, {, r: @1 G1 N7 b( O
--  ------  -----------------------  ---  ---, ~5 ]- Q' T- g# a" N1 L5 T" }; e
1   356     2011-05-04 10:41:00.000  1    0
; r4 i0 J/ @1 C/ D& H2   356     2011-05-04 10:42:00.000  1    02 O6 V9 W) w) O9 c7 B. H
3   356     2011-05-04 10:43:00.000  1    0
: @2 z+ X+ E2 B3 X4   356     2011-05-04 10:45:00.000  1    01 @5 l0 I5 F' L
5   356     2011-05-04 10:47:00.000  1    0
4 L+ R/ f. k/ m' T4 }+ ~& J6   356     2011-05-04 10:48:00.000  0    5
0 o% U8 r: r7 P7   356     2011-05-04 11:14:00.000  1    1  {" D% ?/ c/ X0 L
8   356     2011-05-04 11:14:00.000  1    1
+ \1 Y6 w$ K+ V1 E9   356     2011-05-04 11:15:00.000  1    10 e7 j& A  V# d5 I9 o& @
10  356     2011-05-04 11:15:00.000  1    1
1 Z: m4 O9 l6 Z+ H) L3 o, J$ h9 `11  356     2011-05-04 11:15:00.000  1    19 H) Q) z$ Q9 I+ x) e+ n
12  356     2011-05-04 11:16:00.000  0    10, z0 ]2 E( {5 R" g% @4 I
13  356     2011-05-04 11:16:00.000  0    10+ ]) R/ X& F( [& f" |5 b; j
14  356     2011-05-04 11:16:00.000  0    10
0 z3 a3 F+ ~' v# c: T$ C( a15  356     2011-05-04 14:49:00.000  1    4
7 {" F: c- A7 o# A& j; A8 O7 n; z16  356     2011-05-04 14:50:00.000  1    4
! B5 _. c1 S% Y& j17  356     2011-05-04 14:50:00.000  1    4
! O. o1 \$ g( g1 \$ V0 Q  ?9 y18  356     2011-05-04 14:51:00.000  1    49 L- E" j5 X2 `5 A* S3 r. R
19  356     2011-05-04 14:52:00.000  0    14$ ~9 ?! {  v4 a- \* X
20  356     2011-05-04 14:52:00.000  0    14( o* I  d9 p4 I2 b0 f8 v, |# m& J/ w
21  356     2011-05-04 20:52:00.000  0    14! l8 W' X  W% T
您可以自己了解如何ign通过其自己的键轻松地将具有相同事件的每个事件序列与其他事件区分开(UnitId, ign,* `, V4 l  L5 G; r6 l
Grp)。因此,现在我们可以对每个序列以及序列中的每个事件进行排名,这就是rankedCTE所做的。它产生以下结果集:
( ]( ?& @. X, r9 ~Id  UnitId  eventtime                ign  Grp  seqRank  eventRank
# K' z4 s$ h% Q4 l! W: I7 r/ Y--  ------  -----------------------  ---  ---  -------  ---------% w, N( n& c* U# f0 \5 v; q5 x
1   356     2011-05-04 10:41:00.000  1    0    1        1
) u1 n% l8 a3 i9 A) q% S* }2   356     2011-05-04 10:42:00.000  1    0    1        2
6 j0 ~' p6 ?) ~9 H8 f. O2 k, M3   356     2011-05-04 10:43:00.000  1    0    1        3
+ g  _. q- O4 E) d$ F4   356     2011-05-04 10:45:00.000  1    0    1        43 M: A' I+ H4 B
5   356     2011-05-04 10:47:00.000  1    0    1        5; G* e5 I. s2 p9 }# h
6   356     2011-05-04 10:48:00.000  0    5    1        1
- K: q( F7 \  t% n7   356     2011-05-04 11:14:00.000  1    1    2        12 M- K$ X$ f$ U( \, E* D" ?" K8 D
8   356     2011-05-04 11:14:00.000  1    1    2        2+ r' A/ H, L& ]1 a
9   356     2011-05-04 11:15:00.000  1    1    2        3- s7 {. A: d/ o, W6 `
10  356     2011-05-04 11:15:00.000  1    1    2        4
* b4 ~/ k0 H8 [1 O# K& k% {11  356     2011-05-04 11:15:00.000  1    1    2        51 h+ L( b# z7 T7 I; O$ K7 i
12  356     2011-05-04 11:16:00.000  0    10   2        1
: s1 r6 Y3 u; f0 i- I. J13  356     2011-05-04 11:16:00.000  0    10   2        2
. s) }# |" d  R14  356     2011-05-04 11:16:00.000  0    10   2        3
7 [3 `4 z/ Y* ?3 z$ u15  356     2011-05-04 14:49:00.000  1    4    3        1
! J) n1 a- A+ h. d# H" ^7 \16  356     2011-05-04 14:50:00.000  1    4    3        20 R( g* V5 w- G# M. H9 s1 z% ^" m
17  356     2011-05-04 14:50:00.000  1    4    3        3
  O3 E2 T& m5 i' U18  356     2011-05-04 14:51:00.000  1    4    3        48 D$ p& B# T& J0 \; m2 @
19  356     2011-05-04 14:52:00.000  0    14   3        1
1 v: B+ B  {0 X. h) D1 S( j20  356     2011-05-04 14:52:00.000  0    14   3        2
" v( H9 @- H$ T+ K21  356     2011-05-04 20:52:00.000  0    14   3        3
- I/ C, D# c8 y' t4 X# O! f/ x, ]您可以看到,借助,ign=1现在可以将ign=0序列与序列匹配seqRank。并且仅从每个序列中选择最早的事件(按过滤eventRank=1),我们将获得所有ign=1序列的开始时间和结束时间。因此,finalCTE的结果是:4 f5 B  F5 D5 m# G5 Y& P
UnitId  EventStart               EventEnd7 `! O* X, S$ ^
------  -----------------------  -----------------------; D% V, b' a* f( N! N( r3 C
356     2011-05-04 10:41:00.000  2011-05-04 10:48:00.0009 ^% Q5 V" i# V( G; h. V
356     2011-05-04 11:14:00.000  2011-05-04 11:16:00.000
( U' {5 O. `$ K  e7 O7 ~; A356     2011-05-04 14:49:00.000  2011-05-04 14:52:00.000
- a" Q3 ]+ g4 d! c2 L2 `# ^- Y显然,如果最后一个ign=1序列后面没有ign=0事件,则不会在最终结果中显示它,因为使用上述方法,最后一个ign=1序列将没有匹配的ign=0序列。
5 o3 w, }! V4 l; t$ B6 p在一种可能的情况下,此查询将无法正常使用。这是事件列表以ign=0事件而不是开头的时间ign=1。如果确实可行,则只需将以下过滤器添加到rankedCTE:
$ U3 z0 R# O1 P) \* K4 P1 _/ QWHERE NOT (ign = 0 AND Grp = 0)
1 M# `9 y5 O/ F. A: v: E-- Alternatively: WHERE ign  0 OR Grp  0" {( v; N0 J& \/ }0 C, }+ w
利用以下事实:的第一个值Grp将始终为0。因此,如果0将分配给具有ign=0的事件,则应排除这些事件。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则