回答

收藏

按列和多行分组为一行多列

技术问答 技术问答 120 人阅读 | 0 人回复 | 2023-09-13

请帮我这个:
5 L. f1 v1 l' Q  _: H1 o我想按列TestType分组,但如果它们具有相同的TestType,则应将Result拆分为colunms
# U) D2 p/ `& f8 J5 [CREATE TABLE Result(WorkOrder varchar(10), TestType varchar(20), Result decimal(10,2));7 l5 ]+ p1 V3 u7 Q/ q+ W
INSERT INTO Result (WorkOrder, TestType, Result) VALUES % N: c; F2 ?* C' ~4 @$ g, F% {
('HP19002316','VitaminA', 10.3),( d7 k; P! ?) M0 v% K* m
('HP19002316','VitaminA', 11.3),
) i5 t( i: I$ z9 M('HP19002316','VitaminA', 12.3),9 y: S- l, J" J) p: e; P* S( G1 {; K
('HP19002316','VitaminB', 13.4),
$ Q; _4 A2 S& C' r9 X('HP19002316','VitaminB', 14.4),
9 ?/ d4 P$ H" G* t('HP19002316','VitaminC', 15.5),
8 a9 b; u+ `1 R: Q: c) S: i1 e('HP19002316','VitaminD', 17.0)+ d8 W6 v$ j5 b
我希望SQL以这种格式返回数据
5 k8 s* q, M  E; ]8 SWorkOrder       TestType        Result1   Result2  Result3
; O: m' _# |, t==========================================================( D; N1 N' D2 k
HP19002316      VitaminA        10.3        11.3    12.3    ( E$ ~6 W' Z* H4 ~0 j
HP19002316      VitaminB        13.4        14.4    NULL
) u; ^# [: n( S) n; mHP19002316      VitaminC        15.5        NULL    NULL7 O  L6 y5 W7 w+ B" [1 O; W4 Z
HP19002316      VitaminD        17.0        NULL    NULL
) M$ d8 S0 t! ~) z* `, H4 O: _3 a- NResult#列应该是动态的,因为每个TestType都有很多结果
5 S+ B, G1 w/ r' E5 T; P" ]               
) ]( {0 Q8 `: U& v- v/ H" L解决方案:1 n2 y( [: e5 v6 h8 G4 C
               
3 n/ w, n& V- G2 U/ ^
( V/ b. e1 ?) r9 P+ R$ b4 g+ M- L5 s! j
                正如我在评论中所提到的,这里您需要的是PIVOT或交叉标签;我更喜欢后者,所以我将要使用的东西。
' H9 ^5 b% R! B9 V+ U5 ^对此的非动态解决方案如下:
& C( I0 r  v" M- X: H9 a) b3 x2 \# qWITH RNs AS(
9 \: A/ S3 @7 t* h2 c4 R$ J# d    SELECT WorkOrder,! B( r, Q9 [$ U6 I9 {& y* H- v+ u3 J
           TestType,: ^9 y2 R" h2 Z5 N
           Result,( G( X; g9 w6 s! w% u+ I% d
           ROW_NUMBER() OVER (PARTITION BY WorkOrder, TestType ORDER BY (SELECT NULL)) AS RN --ORDER BY should be your ID/always ascending column
1 f/ w; o! Z4 C& D4 S7 f% G    FROM dbo.Result)
- H6 d8 d* L/ }2 C+ l7 B, v/ U  x. s# ZSELECT WorkOrder,
8 `9 B; ?3 ]: z! K8 b       TestType,+ P  h- P; s1 C, E% v" h. R+ O
       MAX(CASE RN WHEN 1 THEN Result END) AS Result1,  u0 K  r% L' U7 c1 G! G% U
       MAX(CASE RN WHEN 2 THEN Result END) AS Result2,
0 G, X1 {) ?7 r+ P4 m0 Y' f) o       MAX(CASE RN WHEN 3 THEN Result END) AS Result3
6 O: b, Y- o" B5 P2 i: SFROM RNs R/ _' s- g6 Q* X$ e
GROUP BY WorkOrder,
1 T2 j, j  U+ ]( |2 x         TestType;
/ T5 `3 A7 E4 \! M5 f' i但是,问题在于这会将您“锁定”到3个结果中,但是您建议存在不确定数量的结果。因此,您需要一个动态的解决方案。
) C' H; i3 N+ {+ O以下将最多处理100个结果。如果你 需要 更多的列比超过,再加入更多的CROSS JOINs到N的CTE
% T: d4 {* n7 D8 u0 D8 OTally。结果是这样的(非常混乱)。
7 t/ j  d( Y5 Q/ G6 j+ ADECLARE @SQL nvarchar(MAX),9 y+ G2 s0 k( h1 ^# ^
        @CRLF nchar(2) = NCHAR(13) + NCHAR(10),
2 s8 c3 A9 m& H        @MaxTally int;, U3 v4 n4 {/ ^, \" m6 S
SELECT @MaxTally = MAX(C)
8 p2 S/ X' T5 S! w' lFROM (SELECT COUNT(*) AS C! x( x3 o0 C' n  E6 x' K
      FROM dbo.Result* e: L4 F2 b# I; Y5 P# y
      GROUP BY WorkOrder,) N! ?% k0 C/ q9 {9 N
               TestType) R;
: `' r) c  |! K" [1 G4 Q( y& p) yWITH N AS(4 V7 f( A" V" M4 m7 O; T1 }
    SELECT N: {3 Q4 T' a* f& K
    FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),# ~) ]' r1 M- J5 H, S  U
Tally AS(
- u. m8 I9 ?# r( P    SELECT TOP (@MaxTally) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
& E, m' `  ^* f9 Q$ L- I    FROM N N1, N N2) --100 rows, add more Ns for more rows* x  h( x+ N# K* J7 k. n4 Z5 J0 I
SELECT @SQL = N'WITH RNs AS(' + @CRLF +
' c) k8 O  A8 S' Y; G. B              N'    SELECT WorkOrder,' + @CRLF +
3 y; k8 U4 M6 l( ]" q% F7 w  Z              N'           TestType,' + @CRLF +" T' Q5 {2 G% u6 Y. z
              N'           Result,' + @CRLF +
3 @- S, B4 ?7 ^              N'           ROW_NUMBER() OVER (PARTITION BY WorkOrder, TestType ORDER BY (SELECT NULL)) AS RN --ORDER BY should be your ID/always ascending column' + @CRLF +
' I% G) ]- m$ _8 z              N'    FROM dbo.Result)' + @CRLF +
9 C( g: v$ R5 h5 A$ }              N'SELECT WorkOrder,' + @CRLF +
7 d/ o& e# s3 I% p7 m  ^- ^              N'       TestType,' + @CRLF +
9 `2 }( A: n' ]              --Using FOR XML PATH due to not knowing SQL Server version
# Q! r) Y2 b4 D/ C9 x2 t              STUFF((SELECT N',' + @CRLF +
& o0 |  U  D) M- {. b1 l* t; s                            CONCAT(N'       MAX(CASE RN WHEN ',T.I,N' THEN Result END) AS Result',T.I)( v# F; W+ n4 S3 D+ {8 E. X7 I' v
                     FROM Tally T# m: q% l  ~9 I  }
                     ORDER BY T.I ASC
4 c/ H' n: Y$ ]% Q                     FOR XML PATH(N''),TYPE).value('(./text())[1]','nvarchar(MAX)'),1,3,N'') + @CRLF +
- v, @+ h* Z+ q( n% p              N'FROM RNs R' + @CRLF ++ I4 Y$ D5 ^8 @# \9 l# Z
              N'GROUP BY WorkOrder,' + @CRLF +
8 O! O6 R" x2 k              N'         TestType;';
0 S& T! h+ i6 ~$ PPRINT @SQL; --Your best friend.
* J0 M- T; s# y' KEXEC sys.sp_executesql @SQL;
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则