【问题标题】:SQL Pivot - Dynamic Columns, No AggregationSQL Pivot - 动态列,无聚合
【发布时间】:2016-10-04 01:44:47
【问题描述】:

我正在尝试做一个 Pivot,但我对 Pivot 不是很有经验,而且我被卡住了 - 我不知道如何构造查询。

我有什么:

  • 数据类型(记录的测量类型)
  • 地点
  • 数据源(每个位置要测量的东西)
  • 数据读数(来源的测量值)

附加信息:

  • 任何一个位置的源数量都可以改变
  • 一个位置永远不会有超过 5 个来源
  • 每个来源/类型/日期仅保存 1 个读数

在返回的表中:

  • 表格显示单个位置和日期的 Data_Type 信息和读数
  • 列:Data_Name、Units、Is_Required(来自 Data_Type 表),每个 Source 加一列
  • 行:每个 Data_Type 一行
  • 应按 Type_Display_Order 对行进行排序
  • 来源(额外列)应按 Source_Display_Order 排序
  • 有些读数是可选的,有些来源不是每天测量的 - 这些仍然需要包含在表格中

例子:

Table: Data_Type
Data_Type_ID  Data_Name  Units  Is_Required (BIT)  Type_Display_Order
-----------------------------------------------------------------------
1             Height     In.    1                  2
2             Length     In.    0                  3
3             Weight     Lbs.   1                  1

Table: Location
Location_ID  Location
-----------------------
1            West
2            East

Table: Data_Source
Data_Source_ID  Location_ID  Source_Name  Source_Display_Order
----------------------------------------------------------------
1               1            WCS          2
2               2            ECS          1
3               1            WBN          1

Table: Data_Reading
Data_Reading_ID  Data_Type_ID  Data_Source_ID  Reading  Reading_Date
----------------------------------------------------------------------
1                1             1               5        6/3/2016
2                3             2               3        5/1/2016
3                1             1               7        5/1/2016
4                2             3               2        6/3/2016
5                3             1               4        6/3/2016

Location = "West", Date = 6/3/2016 的查询所需结果:

Data_Type_ID  Data_Name  Units  Is_Required  WBN   WCS
---------------------------------------------------------
3             Weight     Lbs.   1            NULL  4
1             Height     In.    1            NULL  5
2             Length     In.    0            NULL  NULL

这个解决方案似乎是类似的:Pivot Dynamic Columns, no Aggregation 但我仍然遇到一些问题。

这是我目前所拥有的:

DECLARE @date DATE, @locationID INT

SET @date = CAST('6/3/2016' AS DATE)
SET @locationID = 1

DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(s.Source_Name)
            FROM Data_Source s
            WHERE s.Location_ID = @locationID
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)')
        ,1,1,'')

SET @query = 'SELECT Data_Type_ID, Data_Name, Units, Is_Required, ' + @cols +
' FROM
(
    SELECT
          t.Data_Type_ID
        , t.Data_Name
        , t.Units
        , t.Is_Required
        , r.Reading
        , s.Source_Name
    FROM
        Data_Type t
    LEFT JOIN
        Data_Reading r ON t.Data_Type_ID = r.Data_Type_ID
    LEFT JOIN
        Data_Source s ON r.Data_Source_ID = s.Data_Source_ID
    WHERE
        r.Reading_Date = CAST(CAST(' + @date + ' AS NVARCHAR(10)) AS DATE)
        AND s.Location_ID = CAST(' + @locationID + ' AS INT)
) x
PIVOT
(
    MIN(Reading)
    for Source_Name in (' + @cols + ')
) p '

我的查询现在可以正常工作,但我仍然有一些问题:

  • @cols 未按 Source_Display_Order 排序
  • 行未按 Type_Display_Order 排序(我在 X 部分的内部 SELECT 语句中确实有 ORDER BY,但我收到错误说我不能在那里有 ORDER BY 子句)
  • WHERE 语句中的日期比较不起作用 - 由于某种原因,它总是计算为 False,即使日期相同

【问题讨论】:

  • 结果表单查询是你想要的吗?如果不是什么是预期的结果。我试图了解您要查询的内容。如果我们能看到正确的结果应该是什么样子,那将会很有帮助。
  • 上面包含了一个示例所需的结果 - 我将标题修改为粗体,以便于查找。此外,我现在确实有查询返回结果没有错误,但它仍然没有做我需要的 - 最后的问题总结在最后的项目符号中。
  • 最后一个问题,结果中的 4 和 5。你是怎么来的?
  • 来自上面的 Data_Reading 表

标签: sql sql-server sql-server-2012 pivot pivot-table


【解决方案1】:

解决了!

DECLARE @date DATE, @locationID INT

SET @date = CAST('6/3/2016' AS DATE)
SET @locationID = 1

DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX)

SET @cols = STUFF((SELECT ',' + QUOTENAME(s.Source_Name)
            FROM Data_Source s
            WHERE s.Location_ID = @locationID
            ORDER BY s.Source_Display_Order
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)')
        ,1,1,'')

SET @query =
'SELECT
      Data_Type_ID
    , Data_Name
    , Units
    , Is_Required
    , ' + @cols + '
FROM
(
    SELECT
          t.Data_Type_ID
        , t.Data_Name
        , t.Units
        , t.Is_Required
        , r.Reading
        , s.Source_Name
        , t.Type_Display_Order
    FROM
        Data_Type t
    LEFT JOIN
        Data_Reading r ON t.Data_Type_ID = r.Data_Type_ID
    LEFT JOIN
        Data_Source s ON r.Data_Source_ID = s.Data_Source_ID
    WHERE
        r.Reading_Date = ''' + CAST(@date AS NVARCHAR(10)) + '''
        AND s.Location_ID = ' + CAST(@locationID AS NVARCHAR(20)) + '
) x
PIVOT
(
    MIN(Reading)
    for Source_Name in (' + @cols + ')
) p
ORDER BY
    Type_Display_Order'

EXECUTE(@query)

解决我的问题:

  • 在添加到 @query 字符串之前将 @date 转换为 NVARCHAR,并在 @query 内的引号中包含额外的引号以将新的 NVARCHAR 括起来
  • 从@cols 中删除 DISTINCT 子句并添加 ORDER BY(我表中的所有名称都是唯一的,因此不需要 DISTINCT)
  • 将 Type_Display_Order 添加到内部 SELECT 语句,并在 PIVOT 语句后添加 ORDER BY

【讨论】:

    猜你喜欢
    • 2014-11-27
    • 2019-02-27
    • 2014-11-26
    • 1970-01-01
    • 2010-11-17
    • 2016-10-16
    • 1970-01-01
    • 2021-12-29
    • 2021-06-03
    相关资源
    最近更新 更多