将SQL行变成列

时间:2019-02-19 11:16:59

标签: sql-server pivot

我已将许多建筑数据从另一个系统导入MS SQL 2017,但面临着将行变成列的问题。在从中导入的系统中,大多数字段都是var-chars,并且一个字段可以具有前导/尾随空格。相信我,我说过,我已经在许多地方/页面中搜索了答案。

data:
key1   Unit       Measurement 
04A    Unit 1     156,8000
04A    Unit 2     5.845,3000
678R   Unit 1     8,6000
678R   Unit 2     409,6000
678R   Unit 3     17

how can data be turned into:
key1   Unit 1     Unit 2       Unit 3
04A    156,8000   5.845,3000   NULL
678R   8,6000     409,6000     17

测量列-应该是浮点数还是小数点-我们在这里是scandinavians :-)吗?

我尝试使用max作为汇总函数进行数据透视,但是在单元1,2,3中出现的行太多,其中包含空值-甚至拒绝具有值的行

3 个答案:

答案 0 :(得分:1)

您可以使用PIVOT运算符:

SELECT * 
FROM 
(
    SELECT * FROM YourTable
)AS FooData
PIVOT(
    AVG(FooData.Measurement)
    FOR Unit IN ([Unit 1], [Unit 2], [Unit 3])
) AS FooPivot

一个例子:

DECLARE @tbl TABLE
(
   key1   varchar(50),
   Unit   VARCHAR(50),
   Measurement DECIMAL(18,8)
)

INSERT INTO @tbl
(
    key1,
    Unit,
    Measurement
)
VALUES
  ('04A', 'Unit 1',     156.8000)
, ('04A', 'Unit 2',     5.8453000)
, ('678R', 'Unit 1',     8.6000)
, ('678R', 'Unit 2',     409.6000)
, ('678R', 'Unit 3',     17)
SELECT * 
FROM 
(
    SELECT * FROM @tbl
)AS FooData
PIVOT(
    AVG(FooData.Measurement)
    FOR Unit IN ([Unit 1], [Unit 2], [Unit 3])
) AS FooPivot

输出:

key1    Unit 1            Unit 2        Unit 3
04A     156.80000000    5.84530000      NULL
678R    8.60000000      409.60000000    17.00000000

更新:

我不知道Measurement字段的实际数据类型是什么5.845,3000,但是我坚信该数据是numeric类型。如果是,那么最好将数字数据存储为数字类型,因为表示层负责,因为在不同国家/地区显示数字有不同的要求。要添加逗号,可以在客户端使用管道。

此外,如果Measurement是数字类型,并且将其存储为varchar(50),则订购时会遇到问题。因此最好将其存储为numeric

否则,您可以使用数据类型varchar(255)

DECLARE @tbl TABLE
(
   key1   varchar(50),
   Unit   VARCHAR(50),
   Measurement VARCHAR(255)
)

INSERT INTO @tbl
(
    key1,
    Unit,
    Measurement
)
VALUES
  ('04A', 'Unit 1',     '156.8000')
, ('04A', 'Unit 2',     '5,845.3000')
, ('678R', 'Unit 1',     '8.6000')
, ('678R', 'Unit 2',     '409.6000')
, ('678R', 'Unit 3',     '17')
SELECT * 
FROM 
(
    SELECT * FROM @tbl
)AS FooData
PIVOT(
    MAX(FooData.Measurement)
    FOR Unit IN ([Unit 1], [Unit 2], [Unit 3])
) AS FooPivot

答案 1 :(得分:1)

您可以使用PIVOT进行尝试。在这里,您需要使用MAX()函数而不是AVG()SUM(),因为保存的数据在varchar中。

create table #temp(key1 varchar(10), Unit Varchar(20), Measurement varchar(20))
insert into #temp values
('04A', 'Unit 1', '156,8000'),
('04A', 'Unit 2', '5.845,3000'),
('678R', 'Unit 1', '8,6000'),
('678R', 'Unit 2', '409,6000'),
('678R', 'Unit 3', '17')

SELECT * 
FROM 
(
    SELECT * FROM #temp
)AS FooData
PIVOT(
    MAX(FooData.Measurement)
    FOR Unit IN ([Unit 1], [Unit 2], [Unit 3])
) AS FooPivot

输出如下所示:

key1    Unit 1      Unit 2      Unit 3
04A     156,8000    5.845,3000  NULL
678R    8,6000      409,6000    17

答案 2 :(得分:0)

在实际应用之前,请确保限制枢轴的列集:

;WITH PrePivot AS -- Limit the columns for the PIVOT's GROUP BY
(
    SELECT
        Key1,
        Unit,
        Measurement
    FROM
        YourTable
)
SELECT
    P.Key1,
    P.[Unit 1],
    P.[Unit 2],
    P.[Unit 3]
FROM
    PrePivot AS T
    PIVOT (
        MAX(T.Measurement) FOR T.Unit IN ([Unit 1], [Unit 2], [Unit 3])
    ) AS P

请检查this post,以了解PIVOT实际上如何对所有非枢轴列执行隐式GROUP BY