我需要使用SQL Server将行转列以显示不同维度的数据或满足表格格式要求。
从这个查询和这个返回开始
SELECT
_p,
_t,
_x,
COUNT (*) _q
FROM
[dbo].[subset_data]
WHERE
CONVERT ( VARCHAR ( 10 ), data, 120 ) = CONVERT ( VARCHAR ( 10 ), GETDATE( ), 120 )
GROUP BY
_p,
_t,
_x;
+--------+--------------+----------+--------+
| _p | _t | _x | _q |
+--------+--------------+----------+--------+
| 001 | 06:00-12:00 | 15 | 1 |
| 001 | 12:00-18:00 | 15 | 1 |
| 008 | 06:00-12:00 | 5 | 2 |
| 009 | 12:00-18:00 | 6 | 1 |
| 010 | 06:00-12:00 | 12 | 1 |
+--------+--------------+----------+--------+
我必须得到这份回报
+--------+--------------+-------------+-------------+-------------+------------+
| _p | 00:00-06:00 | 06:00-12:00 | 12:00-18:00 | 18:00-23:59 | _x |
+--------+--------------+-------------+-------------+-------------+------------+
| 001 | 0 | 1 | 1 | 0 | 15 |
| 008 | 0 | 2 | 0 | 0 | 5 |
| 009 | 0 | 0 | 1 | 0 | 6 |
| 010 | 0 | 1 | 0 | 0 | 12 |
+--------+--------------+-------------+-------------+-------------+------------+
列 _t 的行值要转换为列,对于 _p 列的每个值,我必须从 _q 列检索行的值。
你能帮我吗?
-- INIT database
CREATE TABLE subset_data (
data DATETIME,
_p VARCHAR(100),
_t VARCHAR(100),
_x VARCHAR(100),
);
INSERT INTO subset_data(data, _p, _t, _x) VALUES (GETDATE(), '001', '06:00-12:00', '15');
INSERT INTO subset_data(data, _p, _t, _x) VALUES (GETDATE(), '001', '12:00-18:00', '15' );
INSERT INTO subset_data(data, _p, _t, _x) VALUES (GETDATE(), '008', '06:00-12:00', '5' );
INSERT INTO subset_data(data, _p, _t, _x) VALUES (GETDATE(), '008', '06:00-12:00', '5' );
INSERT INTO subset_data(data, _p, _t, _x) VALUES (GETDATE(), '009', '12:00-18:00', '6');
INSERT INTO subset_data(data, _p, _t, _x) VALUES (GETDATE(), '010', '06:00-12:00', '12');
我尝试使用
PIVOT
如下:
select
_p, _t, _x
from
(
select _p
from [dbo].[subset_data]
) d
pivot
(
_p
for _p in (_p, _t, _x)
) piv;
错误
> Msg 156, Level 15, State 1, Server IT000001861251, Procedure , Line 0
Incorrect syntax near the keyword 'for'.
> [42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Incorrect syntax near the keyword 'for'. (156)
您所做的尝试有很多的缺陷:
d
仅公开列 _p
,因此 _t
和 _x
不可访问。PIVOT
缺少聚合函数。_p
的值,但您想要检查 _t
_p) has the value
'_p',
'_t', or
'_x' but those values never appear in that column, nor the column you actually want to pivot on (
_t`)。IN
子句中有一个尾随逗号。建议的重复内容,在 sql server 中高效地将行转换为列,向您展示了如何正确使用
PIVOT
,其格式为:
SELECT <Columns List from Pivoted derived table>
FROM (SELECT <Columns List>
FROM <Table Name> --Your Table) <Alias>
PIVOT (<Aggregate Expression>
FOR <Column to PIVOT on> IN (<Delimited list of Values to PIVOT on>)) <Pivot Alias>;
对于您的数据,这会产生以下结果:
SELECT _p,
[00:00-06:00],
[06:00-12:00],
[12:00-18:00],
[18:00-23:59],
_x
FROM (SELECT _p,
_t,
_x
FROM [dbo].[subset_data]) d
PIVOT (COUNT(_t)
FOR _t IN ([00:00-06:00],[06:00-12:00],[12:00-18:00],[18:00-23:59])) piv
ORDER BY _p;
不过,就我个人而言,一如既往,我建议条件聚合;语法不那么“笨重”,限制更少,并且(更)可以转移到其他方言:
SELECT _p,
COUNT(CASE _t WHEN '00:00-06:00' THEN 1 END) AS [00:00-06:00],
COUNT(CASE _t WHEN '06:00-12:00' THEN 1 END) AS [06:00-12:00],
COUNT(CASE _t WHEN '12:00-18:00' THEN 1 END) AS [12:00-18:00],
COUNT(CASE _t WHEN '18:00-23:59' THEN 1 END) AS [18:00-23:59],
_x
FROM dbo.subset_data sd
GROUP BY _p,
_x
ORDER BY _p;