简体   繁体   English

SQL Pivot-动态列,无聚合

[英]SQL Pivot - Dynamic Columns, No Aggregation

I'm trying to do a Pivot, but I'm not very experienced with pivots and I'm stuck - I can't figure out how to structure the query. 我正在尝试执行数据透视,但是我对数据透视的经验不是很丰富,而且很棘手-我不知道如何构造查询。

What I have: 我有的:

  • Data Types (types of measurements that are recorded) 数据类型(记录的测量类型)
  • Locations 地点
  • Data Sources (things at each location that will be measured) 数据源(将在每个位置测量的事物)
  • Data Readings (measurements of the sources) 数据读数(源度量)

Additional information: 附加信息:

  • The number of Sources at any one Location can change 任何一个位置的光源数量都可以改变
  • There will never be more than 5 sources at a single Location 一个位置上的来源永远不会超过5个
  • Only 1 Reading is saved per Source/Type/date 每个来源/类型/日期仅保存1个读数

In the returned table: 在返回的表中:

  • Table shows Data_Type info and Readings for a single Location and date 表格显示了单个位置和日期的Data_Type信息和读数
  • Columns: Data_Name, Units, Is_Required (from Data_Type table), plus one column for each Source 列:Data_Name,Units,Is_Required(来自Data_Type表),以及每个Source的一列
  • Rows: one row for each Data_Type 行:每个Data_Type一行
  • Rows should be ordered by Type_Display_Order 行应按Type_Display_Order排序
  • Sources (extra columns) should be ordered by Source_Display_Order 来源(额外的列)应按Source_Display_Order排序
  • Some Readings are optional, and some Sources aren't measured daily - these still need to be included in the table 有些读数是可选的,有些资料不是每天测量的-这些仍需要包含在表格中

Example: 例:

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

Desired results from query for Location = "West", Date = 6/3/2016: 查询位置=“​​ West”,日期= 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

This solution seems to be similar: Pivot Dynamic Columns, no Aggregation but I'm still having some problems. 这个解决方案似乎是相似的: 枢轴动态列,没有聚合,但是我仍然有一些问题。

This is what I have so far: 这是我到目前为止的内容:

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 '

I have the query working properly now, but I still have a few problems: 我的查询现在可以正常工作,但是仍然有一些问题:

  • @cols is not sorted by Source_Display_Order @cols未按Source_Display_Order排序
  • rows are not sorted by Type_Display_Order (I did have ORDER BY in the inner SELECT statement for part X, but I was getting errors saying I can't have an ORDER BY clause there) 行未按Type_Display_Order排序(我在X部分的内部SELECT语句中确实有ORDER BY,但我收到错误消息说那里没有ORDER BY子句)
  • Date comparison in WHERE statement doesn't work - for some reason, it always computes as False, even when the dates are the same WHERE语句中的日期比较不起作用-出于某种原因,即使日期相同,也总是将其计算为False

Solved! 解决了!

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)

To fix my problems: 解决我的问题:

  • Convert @date to NVARCHAR before adding to @query string and include extra quotes to surround the new NVARCHAR in quotes within @query 将@date转换为NVARCHAR,然后再添加到@query字符串中,并在@query内的引号中包含额外的引号以将新的NVARCHAR括起来
  • Remove DISTINCT clause from @cols and add ORDER BY (all of the names in my table are unique, so the DISTINCT is unnecessary) 从@cols中删除DISTINCT子句并添加ORDER BY(我表中的所有名称都是唯一的,因此DISTINCT是不必要的)
  • Add Type_Display_Order to the inner SELECT statement, and add ORDER BY after the PIVOT statement 将Type_Display_Order添加到内部SELECT语句中,并在PIVOT语句之后添加ORDER BY

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM