回答

收藏

ROW_NUMBER()OVER(PARTITION BY')使用麻烦

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

我正在使用SQL Server 2008 R2。我有一个名为EmployeeHistory的表,具有以下结构和示例数据:
; ?4 T) G- v( b+ MEmployeeID Date      DepartmentID SupervisorID
) f4 }- W. e) X# D7 X0 g10001      20130101  001          10009, Z+ c/ m/ f* \3 W% q0 M+ x' B
10001      20130909  001          100196 P) |; p2 l5 j/ |' D
10001      20131201  002          10018
1 |! {' X: n! X0 m10001      20140501  002          100175 I6 |, ~9 Z2 c
10001      20141001  001          10015( O( o# s& q* V7 V! n( n0 L
10001      20141201  001          10014
" n1 o+ l; Q$ o' R请注意,随着时间的推移,员工10001一直在更改2个部门和几个主管。我要做的是在“日期”字段中按顺序列出每个部门中该雇员的工作的开始和结束日期。因此,输出将如下所示:
! u( }- g4 h4 ~2 L3 OEmployeeID DateStart DateEnd  DepartmentID 8 I8 S( t. l! u# [
10001      20130101  20131201 0013 i' E4 q! s4 F0 h; x7 U' X
10001      20131201  20141001 002
, j1 |2 w* a4 r10001      20141001  NULL     001
0 \1 y0 n: f% N我打算使用以下查询对数据进行分区,但失败了。部门从001更改为002,然后又更改为001。显然,我无法按DepartmentID进行分区…我敢肯定,我忽略了明显的部分。有什么帮助吗?先感谢您。
5 K5 G1 ~4 G& e: T0 e5 O0 N/ a, eSELECT * ,ROW_NUMBER() OVER (PARTITION BY EmployeeID, DepartmentID/ l1 `7 k& h7 f  \+ v, K$ y
ORDER BY [Date]) RN FROM EmployeeHistory
% C: [  X1 D: e  T                " |& y0 s: q/ f: ~+ P
解决方案:
& p  E4 ~5 u  L$ Z4 N               
& l% ^- ^. y; \+ h: m2 k+ d5 o" `$ K! v% K3 f

1 `) a% G: {6 r5 K. p                有点涉及。最简单的方法是参考我为您创建的SQL
/ |- O3 S* E0 P  oFiddle,它产生确切的结果。您可以通过多种方法出于性能或其他方面的考虑对其进行改进,但是至少应该比某些替代方法更清楚一些。0 i3 C  }3 E  i+ D' m2 ?4 d
要点是,首先要获得数据的规范排名,然后使用该排名将数据划分为组,然后为每个组找到结束日期,然后消除任何中间行。ROW_NUMBER()和CROSS
5 t( B$ \3 A/ ]# W! {. pAPPLY在可读性方面有很大帮助。+ o! U/ s& S! h1 [
+ L' _, Q$ W. ]. z5 w
编辑2019:6 d/ c; u% V5 Q; j" P# w% P
实际上,由于某种原因,SQL Fiddle确实确实坏了,但是在SQL Fiddle站点上似乎是一个问题。这是一个完整的版本,刚刚在SQL Server0 [% D) v, s1 i4 N$ C
2016上进行了测试:
9 A! T( {- q% ^, I3 ECREATE TABLE Source4 h* z& W+ u2 F" x, d+ Y) a+ f
(
( i$ P9 b; W8 X, }8 J  u# R  EmployeeID int,' `- ?# ?# {/ @! u% m8 k; Z, r
  DateStarted date,2 x0 w/ w( G& r
  DepartmentID int
* w9 b; H/ }& r)% W! b0 b0 O$ f, [
INSERT INTO Source
* c2 f# W7 }. M9 [0 D7 FVALUES  ], m  }) y" ]
(10001,'2013-01-01',001),
, @& Z) _) ]$ i- E(10001,'2013-09-09',001),. z' ?- N$ i$ }  u' h5 ~2 ~8 p
(10001,'2013-12-01',002),
% u% a+ P& k+ e5 W$ t( B* U(10001,'2014-05-01',002),
; i1 |' v; Y& y  y5 h  h# p(10001,'2014-10-01',001),
8 [; c: c) i6 Y- P3 d5 [(10001,'2014-12-01',001)
+ _: T- h; j; Q7 z  \: `# z; X, i
5 u+ @5 A4 @) R3 g. H5 d5 m/ aSELECT *, $ B8 Z2 m3 `) N+ b  `7 y6 c2 K. @$ a
  ROW_NUMBER() OVER (PARTITION BY EmployeeID ORDER BY DateStarted) AS EntryRank,# a1 {7 p7 W  D
  newid() as GroupKey,& l# Y6 Y) D( F
  CAST(NULL AS date) AS EndDate
3 z7 ]9 D. s# V$ Q( F+ f! f* p- CINTO #RankedData/ |) v% I* b8 {3 ^0 @0 B# L
FROM Source9 a9 T! p3 D3 G9 R4 j2 u" c6 b
;
# O; }* c' t6 d/ {* B" D! fUPDATE #RankedData
7 [! K" v. w  `, a. U6 d" I: SSET GroupKey = beginDate.GroupKey( R: _: v* U, [2 }  O
FROM #RankedData sup6 e3 s4 A  O" G  d" y, m
  CROSS APPLY 0 ^: s: Q: |' S2 B
  (
) h, J7 b( x1 v+ h0 t( K. Q    SELECT TOP 1 GroupKey
" @) v$ Z. @/ k) _) q    FROM #RankedData sub 3 R4 G, _  H( ]$ ?/ J- r
    WHERE sub.EmployeeID = sup.EmployeeID AND6 V( B1 s$ D4 z. T( m' r8 G
      sub.DepartmentID = sup.DepartmentID AND
* ^* x' K1 i# C      NOT EXISTS ! V& J; ^) k2 I+ s4 i
        (/ |2 C' u1 W0 D& X
          SELECT * - O! a8 A* t: L1 w, F' q: s
          FROM #RankedData bot ! `4 S+ a+ t8 W% z; R) W
          WHERE bot.EmployeeID = sup.EmployeeID AND( r0 X6 \* X3 D) r; A; Y
            bot.EntryRank BETWEEN sub.EntryRank AND sup.EntryRank AND
# ], [7 p. K9 l/ m, d            bot.DepartmentID  sup.DepartmentID6 w' i/ q) E6 K4 F4 z
        )
+ K* |6 ^9 _1 Z) k4 D      ORDER BY DateStarted ASC
" i& n/ _' W- E7 Q    ) beginDate (GroupKey);' d( w$ _" b4 l- `
UPDATE #RankedData
# J; n" C+ \* M8 P! dSET EndDate = nextGroup.DateStarted  z+ D6 x. T8 t+ Q4 ?" Q
FROM #RankedData sup% c8 i& p' a0 ?" ^1 I
  CROSS APPLY 1 `, M, I1 U" H4 f' }% @) Z
  (  Y* k7 Y3 p5 s: q% p5 s9 e- o
    SELECT TOP 1 DateStarted" y" P) E- U. ]: [  C, i2 B
    FROM #RankedData sub
6 m  |. t& x# S5 q8 P( S) L    WHERE sub.EmployeeID = sup.EmployeeID AND7 y% C( Y2 I5 _8 c8 X) |2 r8 E% K* n
      sub.DepartmentID  sup.DepartmentID AND* m3 s4 }/ F0 R) j+ \. u7 T
      sub.EntryRank > sup.EntryRank
- z: s+ S7 A9 Z4 T( A2 F* u3 m    ORDER BY EntryRank ASC( g0 `( {- Q- V" M* x( f6 y3 x
  ) nextGroup (DateStarted);3 [& x7 j2 ~; ^' E5 V  E" c& a% j; `
SELECT * FROM + N2 |! g" E7 S( `$ d6 A4 x
(
- k6 y6 ?7 B& n3 W! mSELECT *, ROW_NUMBER() OVER (PARTITION BY GroupKey ORDER BY EntryRank ASC) AS GroupRank FROM #RankedData
1 X- X" |4 r0 G. H6 V$ M) FinalRanking
) H: A. `$ r5 n% eWHERE GroupRank = 1
7 |: l% R5 b( zORDER BY EntryRank;8 j; Y- |, B& `3 t4 c5 }
DROP TABLE #RankedData
4 e4 T$ X5 j0 U9 J3 V! u" yDROP TABLE Source
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则