SQL Server 将行转置为列

问题描述 投票:0回答:1

我需要使用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');

SQLFiddle

我尝试使用

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)
sql sql-server pivot pivot-table
1个回答
0
投票

您所做的尝试有很多的缺陷:

  1. 您的派生表
    d
    仅公开列
    _p
    ,因此
    _t
    _x
    不可访问。
  2. 您的
    PIVOT
    缺少聚合函数。
  3. 您正在尝试检查
    _p
    的值,但您想要检查
    _t
  4. 您正在检查该列是否 (
    _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`)。
  5. 您的
    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;
© www.soinside.com 2019 - 2024. All rights reserved.