【问题标题】:sql table pivot or transformsql 表透视或转换
【发布时间】:2012-02-02 21:52:50
【问题描述】:

我有一个如下的数据表

User Year  Points  Value
A    1997  1       10
A    1997  2       30
A    1997  3       40
A    1999  1       70
B    1993  1       7
B    1993  3       4
C    2001  1       10
.....

我希望将表格转换成这样:

User   Year  Points1  Points2  Points3 ....
A      1997  10       30       40
A      1999  70       null     null
B      1993  7        null     4
C      2001  10       null     null
......

Points 的范围在编译时是未知的,所以不只是从 1 到 3。 这几乎就像将点作为新表中的列标题一样。我想 SQL PIVOT 是一个不错的选择,但我没有任何运气玩它。我正在使用 SQL 2008。

【问题讨论】:

  • 您使用的是哪个数据库?

标签: sql sql-server-2008 pivot


【解决方案1】:

既然你提到了SQL PIVOT,我猜你正在使用 SQL Server 2005 或更高版本或 Oracle 11g

SQL 2005

SELECT [user], year, [1] as Point1, [2] as Point2, [3] as Point3 
FROM
(

SELECT  [user], year , points, Value
    FROM table ) AS SourceTable
PIVOT
(
SUM(Value)
FOR Points IN ([1], [2], [3])
) AS PivotTable
ORDER BY [user]

data.se query查看工作示例

Oracle 11g

如果您使用的是 Oracle 11g,它会是这样的(不确定字段别名)

SELECT *
FROM   (
        SELECT  user, year , points, Value
        FROM table )
PIVOT  (SUM(Value) AS sum_value FOR (Points ) IN ('1' as Point1 , 
                                                  '2' as Point2, 
                                                 '3' as Point3))
Order by User;

【讨论】:

  • 对不起,我忘了说Points的范围在编译时是未知的,所以不只是从1到3
  • 那么您需要执行上述操作,但使用动态 SQL 请参阅 T-SQL Pivot? Possibility of creating table columns from row values
  • 感谢您的重播,我尝试了您的 SQL,并正确设置了 User 和 Year 列,但其他列显示为 NULL。
  • 它在data.se example 中工作。您可能需要共享您的 sql。
  • 似乎是数据导致问题,我用的是:('J',1988, 1988, 10), ('W', 1989, 1989, 10), ('W' , 1989, 1990, 20), ('W', 1989, 1991, 30), ('W', 1989, 1992, 40)
【解决方案2】:

也许这会有所帮助:

首先创建一些测试数据:

CREATE TABLE tblPoints ([User] VARCHAR(100), [Year] INT,Points INT,Value INT)
INSERT INTO tblPoints
SELECT 'A',1997,1,10 UNION ALL
SELECT 'A',1997,2,30 UNION ALL
SELECT 'A',1997,3,40 UNION ALL
SELECT 'A',1999,1,70 UNION ALL
SELECT 'B',1993,1,7 UNION ALL
SELECT 'B',1993,3,4 UNION ALL
SELECT 'C',2001,1,10

连接列:

DECLARE @cols VARCHAR(MAX)
SELECT  @cols = COALESCE(@cols + ','+QUOTENAME('Points'+Points),
                     QUOTENAME('Points'+Points))
FROM
    (
        SELECT
            ROW_NUMBER() OVER(PARTITION BY tblPoints.Points ORDER BY tblPoints.Points) AS RowNbr,
            CAST(tblPoints.Points AS VARCHAR(5)) AS Points
        FROM 
            tblPoints
    ) AS tbl
WHERE
    tbl.RowNbr=1

然后创建动态sql并执行:

DECLARE @query NVARCHAR(4000)=
N'SELECT
    *
FROM
(
    SELECT
        tblPoints.[User],
        tblPoints.[Year],
        ''Points''+CAST(tblPoints.Points AS VARCHAR(5)) AS Points,
        tblPoints.Value
    FROM
        tblPoints
) AS p
PIVOT
(
    SUM(Value) FOR Points IN('+@cols+')
) AS pvt
ORDER BY [User]'

EXECUTE(@query)

因为我不想要点表:

DROP TABLE tblPoints

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多