将行值转换为列值 SQL PIVOT
Making row values into column values SQL PIVOT
SQL Returns 以下结果来自 table
+-----+----+-----+----+----+
| PID | PY | QTY | TS | TM |
+-----+----+-----+----+----+
| 99 | CT | 1 | 1 | 6 |
| 99 | E | 3 | 1 | 5 |
| 99 | GR | 4 | 1 | 6 |
+-----+----+-----+----+----+
我想使用 PIVOT(如果可能的话)使结果如下:
+-----+----+-----+----+----+----+------+------+------+------+------+------+------+
| PID | PY | QTY | TS | TM | PY | QTY | TS | TM | PY | QTY | TS | TM |
+-----+----+-----+----+----+----+------+------+------+------+------+------+------+
| 99 | CT | 1 | 1 | 6 | E | 3 | 1 | 5 | GR | 4 | 1 | 6 |
| 100 | V | 6 | 6 | 2 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+-----+----+-----+----+----+----+------+------+------+------+------+------+------+
如果您的值数量有限,那么获得结果的最简单方法是使用带有一些 CASE 表达式的聚合函数。
select
pid,
PY1 = max(case when py = 'CT' then PY end),
QTY1 = max(case when py = 'CT' then QTY else 0 end),
TS1 = max(case when py = 'CT' then TS else 0 end),
TM1 = max(case when py = 'CT' then TM else 0 end),
PY2 = max(case when py = 'E' then PY end),
QTY2 = max(case when py = 'E' then QTY else 0 end),
TS2 = max(case when py = 'E' then TS else 0 end),
TM2 = max(case when py = 'E' then TM else 0 end),
PY3 = max(case when py = 'GR' then PY end),
QTY3 = max(case when py = 'GR' then QTY else 0 end),
TS3 = max(case when py = 'GR' then TS else 0 end),
TM3 = max(case when py = 'GR' then TM else 0 end),
PY4 = max(case when py = 'V' then PY end),
QTY4 = max(case when py = 'V' then QTY else 0 end),
TS4 = max(case when py = 'V' then TS else 0 end),
TM4 = max(case when py = 'V' then TM else 0 end)
from yourtable
group by pid;
参见 SQL Fiddle with Demo。您可以使用 PIVOT 来获得结果,但它会更混乱,因为您需要先取消对多列的透视,然后再对它们进行透视。如果要使用数据透视功能,则必须执行以下操作。
首先,使用row_number()
为每个pid
组合分配一个唯一值:
select pid, py, qty, ts, tm,
rn = row_number() over(partition by pid order by pid)
from yourtable
然后逆透视多列 py
、qty
、ts
和 tm
:
select
pid,
new_col = col + cast(rn as varchar(10)),
val
from
(
select pid, py, qty, ts, tm,
rn = row_number() over(partition by pid order by pid)
from yourtable
) d
cross apply
(
select 'py', py union all
select 'qty', cast(qty as varchar(10)) union all
select 'ts', cast(ts as varchar(10)) union all
select 'tm', cast(tm as varchar(10))
) c (col, val)
我使用 CROSS APPLY
将多列转换为多行。最后,您将旋转 new_col
及其相应的值:
select pid,
py1, qty1, ts1, tm1, py2, qty2, ts2, tm2,
py3, qty3, ts3, tm3, py4, qty4, ts4, tm4
from
(
select
pid,
new_col = col + cast(rn as varchar(10)),
val
from
(
select pid, py, qty, ts, tm,
rn = row_number() over(partition by pid order by pid)
from yourtable
) d
cross apply
(
select 'py', py union all
select 'qty', cast(qty as varchar(10)) union all
select 'ts', cast(ts as varchar(10)) union all
select 'tm', cast(tm as varchar(10))
) c (col, val)
) src
pivot
(
max(val)
for new_col in (py1, qty1, ts1, tm1, py2, qty2, ts2, tm2,
py3, qty3, ts3, tm3, py4, qty4, ts4, tm4)
) piv;
两个版本的最终结果相同。
| pid | py1 | qty1 | ts1 | tm1 | py2 | qty2 | ts2 | tm2 | py3 | qty3 | ts3 | tm3 | py4 | qty4 | ts4 | tm4 |
|-----|-----|------|-----|-----|-----|------|-----|-----|-----|------|-----|-----|--------|--------|--------|--------|
| 99 | CT | 1 | 1 | 6 | E | 3 | 1 | 5 | GR | 4 | 1 | 6 | (null) | (null) | (null) | (null) |
SQL Returns 以下结果来自 table
+-----+----+-----+----+----+
| PID | PY | QTY | TS | TM |
+-----+----+-----+----+----+
| 99 | CT | 1 | 1 | 6 |
| 99 | E | 3 | 1 | 5 |
| 99 | GR | 4 | 1 | 6 |
+-----+----+-----+----+----+
我想使用 PIVOT(如果可能的话)使结果如下:
+-----+----+-----+----+----+----+------+------+------+------+------+------+------+
| PID | PY | QTY | TS | TM | PY | QTY | TS | TM | PY | QTY | TS | TM |
+-----+----+-----+----+----+----+------+------+------+------+------+------+------+
| 99 | CT | 1 | 1 | 6 | E | 3 | 1 | 5 | GR | 4 | 1 | 6 |
| 100 | V | 6 | 6 | 2 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+-----+----+-----+----+----+----+------+------+------+------+------+------+------+
如果您的值数量有限,那么获得结果的最简单方法是使用带有一些 CASE 表达式的聚合函数。
select
pid,
PY1 = max(case when py = 'CT' then PY end),
QTY1 = max(case when py = 'CT' then QTY else 0 end),
TS1 = max(case when py = 'CT' then TS else 0 end),
TM1 = max(case when py = 'CT' then TM else 0 end),
PY2 = max(case when py = 'E' then PY end),
QTY2 = max(case when py = 'E' then QTY else 0 end),
TS2 = max(case when py = 'E' then TS else 0 end),
TM2 = max(case when py = 'E' then TM else 0 end),
PY3 = max(case when py = 'GR' then PY end),
QTY3 = max(case when py = 'GR' then QTY else 0 end),
TS3 = max(case when py = 'GR' then TS else 0 end),
TM3 = max(case when py = 'GR' then TM else 0 end),
PY4 = max(case when py = 'V' then PY end),
QTY4 = max(case when py = 'V' then QTY else 0 end),
TS4 = max(case when py = 'V' then TS else 0 end),
TM4 = max(case when py = 'V' then TM else 0 end)
from yourtable
group by pid;
参见 SQL Fiddle with Demo。您可以使用 PIVOT 来获得结果,但它会更混乱,因为您需要先取消对多列的透视,然后再对它们进行透视。如果要使用数据透视功能,则必须执行以下操作。
首先,使用row_number()
为每个pid
组合分配一个唯一值:
select pid, py, qty, ts, tm,
rn = row_number() over(partition by pid order by pid)
from yourtable
然后逆透视多列 py
、qty
、ts
和 tm
:
select
pid,
new_col = col + cast(rn as varchar(10)),
val
from
(
select pid, py, qty, ts, tm,
rn = row_number() over(partition by pid order by pid)
from yourtable
) d
cross apply
(
select 'py', py union all
select 'qty', cast(qty as varchar(10)) union all
select 'ts', cast(ts as varchar(10)) union all
select 'tm', cast(tm as varchar(10))
) c (col, val)
我使用 CROSS APPLY
将多列转换为多行。最后,您将旋转 new_col
及其相应的值:
select pid,
py1, qty1, ts1, tm1, py2, qty2, ts2, tm2,
py3, qty3, ts3, tm3, py4, qty4, ts4, tm4
from
(
select
pid,
new_col = col + cast(rn as varchar(10)),
val
from
(
select pid, py, qty, ts, tm,
rn = row_number() over(partition by pid order by pid)
from yourtable
) d
cross apply
(
select 'py', py union all
select 'qty', cast(qty as varchar(10)) union all
select 'ts', cast(ts as varchar(10)) union all
select 'tm', cast(tm as varchar(10))
) c (col, val)
) src
pivot
(
max(val)
for new_col in (py1, qty1, ts1, tm1, py2, qty2, ts2, tm2,
py3, qty3, ts3, tm3, py4, qty4, ts4, tm4)
) piv;
两个版本的最终结果相同。
| pid | py1 | qty1 | ts1 | tm1 | py2 | qty2 | ts2 | tm2 | py3 | qty3 | ts3 | tm3 | py4 | qty4 | ts4 | tm4 |
|-----|-----|------|-----|-----|-----|------|-----|-----|-----|------|-----|-----|--------|--------|--------|--------|
| 99 | CT | 1 | 1 | 6 | E | 3 | 1 | 5 | GR | 4 | 1 | 6 | (null) | (null) | (null) | (null) |