【问题标题】:Three column SQL PIVOT三列 SQL PIVOT
【发布时间】:2012-01-13 15:33:30
【问题描述】:

如何使用 SQL PIVOT 命令对看起来像这样的数据进行 sql 数据透视?

id           |    field     |   value
---------------------------------------
1            |    year      |   2011
1            |    month     |   August
2            |    year      |   2009
1            |    day       |   21
2            |    day       |   31
2            |    month     |   July
3            |    year      |   2010
3            |    month     |   January
3            |    day       |   NULL

变成这样的东西:

id  |  year  |  month  |  day
-----------------------------
1     2011     August    21
2     2010      July     31
3     2009     January   NULL

【问题讨论】:

  • 最好是更改表,而不是进行花哨的查询以使其看起来像应该的那样。
  • @Ben - 同意,有更好的方法来存储这些数据,即使考虑到某些“字段”可能需要null。如果这些月份名称实际上是字符串,请向设计师开枪。破坏决定为day 属性存储null 键值的人(而不是完全放弃该属性)。我不确定为什么要这样设置,但我相信日历表 + 日期部分表(和几个视图)会占用更少的空间,提供 FK/数据类型安全,并且可能性能更高。
  • 这是一个常见的场景,由开发人员创建一个元数据表,希望在与每个 ID 关联的元数据字段的数量方面具有灵活性。

标签: sql sql-server-2008 pivot


【解决方案1】:

试试这样的:

DECLARE @myTable AS TABLE([ID] INT, [Field] VARCHAR(20), [Value] VARCHAR(20))
INSERT INTO @myTable VALUES ('1', 'year', '2011')
INSERT INTO @myTable VALUES ('1', 'month', 'August')
INSERT INTO @myTable VALUES ('2', 'year', '2009')
INSERT INTO @myTable VALUES ('1', 'day', '21')
INSERT INTO @myTable VALUES ('2', 'day', '31')
INSERT INTO @myTable VALUES ('2', 'month', 'July')
INSERT INTO @myTable VALUES ('3', 'year', '2010')
INSERT INTO @myTable VALUES ('3', 'month', 'January')
INSERT INTO @myTable VALUES ('3', 'day', NULL)

SELECT [ID], [year], [month], [day]
FROM
(
      SELECT [ID], [Field], [Value] FROM @myTable
) t
PIVOT
(
    MIN([Value]) FOR [Field] IN ([year], [month], [day]) 
) AS pvt
ORDER BY pvt.[year] DESC

这将产生以下结果:

ID  year    month   day
1   2011    August  21
3   2010    January NULL
2   2009    July    31

【讨论】:

    【解决方案2】:
    ;WITH DATA(id,field,value) AS
    (
    SELECT 1,'year','2011' UNION ALL
    SELECT 1,'month','August' UNION ALL
    SELECT 2,'year','2009' UNION ALL
    SELECT 1,'day ','21' UNION ALL
    SELECT 2,'day ','31' UNION ALL
    SELECT 2,'month','July' UNION ALL
    SELECT 3,'year','2010' UNION ALL
    SELECT 3,'month','January' UNION ALL
    SELECT 3,'day ',NULL
    )
    SELECT id,
           year,
           month,
           day
    FROM   DATA PIVOT (MAX(value) FOR field IN ([year], [month], [day])) AS Pvt  
    

    【讨论】:

    • 这个答案也有效。你的两个答案都非常相似......我给了rsbarro点。不过感谢您的帮助。
    【解决方案3】:
    SELECT
    id,
    MAX(CASE WHEN RK=3 THEN VAL ELSE '' END) AS "YEAR",
    MAX(CASE WHEN RK=2 THEN VAL ELSE '' END) AS "MONTH",
    MAX(CASE WHEN RK=1 THEN VAL ELSE '' END) AS "DAY"
    
    FROM 
    (
    SELect
    ID,
    ROW_NUMBER() OVER(PARTITION BY ID ORDER BY YEAR1 ASC) RK,
    VAL
    FROM TEST3)A
    GROUP BY 1
    ORDER BY 1;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-02
      • 2020-10-01
      • 2021-02-03
      • 2020-07-02
      • 1970-01-01
      相关资源
      最近更新 更多