回答

收藏

如何在sql中创建查询以透视数据?

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

我有两个表命名PRODUCT和DETAIL  @/ m2 l, ?. H+ e
TABLE: PRODUCT
3 E: ~+ s* l' D' |' Z  f" gslno  product' e8 r; w6 @6 c5 w+ C7 {0 k1 c, }
1          x    * Z) v& S/ H& c
2          y- Q$ F# b4 x/ ^/ V
3          z
- U) F( r# G4 }+ H) rTABLE: DETAIL" f. ^/ [5 F8 L7 q! u% v- J
product    detail8 N" s' X' k+ p# j
x          good
1 S5 X0 d3 o  k/ Oy          bad8 O/ u. ]8 J) H  [
z          worse0 D$ J2 \. W+ ]( T
x          bad
, {: ~) \0 @( e. s+ j我需要获得输出
4 K4 Q( I/ C% p* Y1 B. m9 WTABLE
* E, j& |! _2 l) X9 p/ eX      Y       Z
2 G& @# v: v- egood   bad     worse
3 g. S2 u# T7 y3 s: gbad
$ t- q. k7 F4 v0 y& v! p. ^                $ C/ C1 x- [4 A8 F2 q
解决方案:4 D6 c4 n2 t" v
                + r0 U% f6 Q* R( X% {% O

& p5 ?- ?- x; N% U# M" o" ~) w- i) L0 q& ]
                此数据转换称为A PIVOT,从SQL Server 2005开始,具有将数据从行转换为列的功能。% |. }0 x% C  y% m8 d! J
有多种方法可以完成此操作,具体取决于您是否有要转换为列的静态数量的值。所有这些都涉及向row_number()数据添加a
5 u: u- e6 s6 D2 Z" R" h" T,因此您可以返回任何产品的多行。
# y; J# m0 A$ V您可以将聚合函数与CASE表达式一起使用:1 F' T. W$ `# Y) m8 ?8 @
select 8 M. D$ F3 I& @: n& Z; ?
  max(case when product = 'x' then detail end) x,+ L+ ^: f  y- c6 u1 g( ?
  max(case when product = 'y' then detail end) y,
4 k, b; w8 c; g% ^4 C8 A  max(case when product = 'z' then detail end) z
! ]9 ]# L% d1 m) ]" F0 nfrom
+ c! G6 I: i- a  E# J1 N(3 ?: ^5 V$ y" U7 ?% s. l
  select p.product, d.detail,
. s/ n8 D/ g- V    row_number() over(partition by p.product order by p.slno) rn; o7 Z8 B6 ~/ s" b- f# ~
  from product p
' Y3 q& y% B# p  inner join detail d- h& `4 i, Q3 P: O
    on p.product = d.product
9 E& G# @0 W( o/ r+ I& b) src8 T- `# z( l- D2 B
group by rn
( N; r# j# n$ x# B参见带有演示的SQL Fiddle- J9 P5 C& o9 r5 i& s
您可以使用以下PIVOT功能:
$ V: m1 R+ J4 Yselect x, y, z
) _% r/ M0 ~( z" V$ n: d9 Tfrom" O# N- Z* F! c+ X  ?# m6 p
(
6 G' t/ x0 h; g7 Z2 V* P- i- A' i  select p.product, d.detail," h' ?: S  b% ?1 ~; o
    row_number() over(partition by p.product order by p.slno) rn
2 p0 G- u; Z* R+ f/ K7 ?. C  from product p# f  D& o* j% N2 \+ S5 A
  inner join detail d
  M. }* N; F9 E3 i) j2 i. g    on p.product = d.product' z: t, g7 }+ o1 Y
) src
7 U* p1 `  k% f3 Q/ Wpivot2 y" T; M4 K& C- O; Y7 Q
(# I$ I0 C+ H. |% @/ T
  max(detail)5 i) c6 Q( Q8 I: r' p
  for product in (x, y, z)/ G( e& Q. r  `5 E% }& p1 E
) piv9 [# k6 q( G1 `0 z, Y
请参阅带有演示的SQL Fiddle。/ l3 j! F4 |1 M
如果您有未知数量的值(在这种情况下为产品)要转换为列,那么您将要使用动态SQL:
* x: R; ]" r# h9 eDECLARE @cols AS NVARCHAR(MAX),2 ^  R) e3 t! K  ]
    @query  AS NVARCHAR(MAX)9 n# }0 I( t# i
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(product)
7 I5 T  U( F; v                    from product1 s/ X, w2 t6 t
            FOR XML PATH(''), TYPE
/ }& P* g2 d% `  A            ).value('.', 'NVARCHAR(MAX)')
$ }1 z7 V8 P# e7 S6 F1 g: s: G4 [) u        ,1,1,'')  S4 _/ P+ {4 l  i( P: Z
set @query = 'SELECT ' + @cols + ' from
6 u4 Q9 F) I* @& K             (
. V, N. w+ s4 c% g1 J                select p.product, d.detail,' Y& \. Z" A/ E3 D% F$ ?  J
                  row_number() over(partition by p.product order by p.slno) rn
" g- T) ?- F3 v" E! t; p                from product p
% H( p" A7 D- `2 `                inner join detail d
0 G+ N2 R& ^! ^. R: d( ?% `                  on p.product = d.product2 `- k) A2 L2 R
            ) x
/ u( }3 N' g' z3 F6 ^, {            pivot
1 E7 l# s: h' O" ]. L6 V5 T8 X* O  ]            (
9 k  a$ {! t% N8 [! x/ V. C1 d                max(detail)! D2 d3 p- R$ M9 c$ N( X2 \! p
                for product in (' + @cols + ')0 [  P: z. L) d+ \/ h) \* o
            ) p '0 J( p& ^& D) j! p) k: j
execute(@query)! s- ?6 T# r+ L& I
参见带有演示的SQL Fiddle
- S, r! E' T" G% J8 d9 D. l所有查询的结果是:8 d- e8 u$ X& P
|    X |      Y |      Z |6 a4 r$ j  h* @$ A1 E1 e
--------------------------
4 ^! `) p$ ?' W* G" H| good |    bad |  worse |2 z( J" \, J; W) l+ {  `
|  bad | (null) | (null) |
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则