【问题标题】:Getting values from a table that's inside a table (unpivot / cross apply)从表内的表中获取值(反透视/交叉应用)
【发布时间】:2017-12-02 00:08:45
【问题描述】:

我的一个导入表存在严重问题。我已将 Excel 文件导入到 SQL Server 表中。表ImportExcelFile 现在看起来像这样(简化):

+----------+-------------------+-----------+------------+--------+--------+-----+---------+
| ImportId | Excelfile         | SheetName | Field1     | Field2 | Field3 | ... | Field10 |
+----------+-------------------+-----------+------------+--------+--------+-----+---------+
|    1     | C:\Temp\Test.xlsx | Sheet1    | Age / Year | 2010   | 2011   |     | 2018    |
|    2     | C:\Temp\Test.xlsx | Sheet1    | 0          | Value1 | Value2 |     | Value9  |
|    3     | C:\Temp\Test.xlsx | Sheet1    | 1          | Value1 | Value2 |     | Value9  |
|    4     | C:\Temp\Test.xlsx | Sheet1    | 2          | Value1 | Value2 |     | Value9  |
|    5     | C:\Temp\Test.xlsx | Sheet1    | 3          | Value1 | Value2 |     | Value9  |
|    6     | C:\Temp\Test.xlsx | Sheet1    | 4          | Value1 | Value2 |     | Value9  |
|    7     | C:\Temp\Test.xlsx | Sheet1    | 5          | NULL   | NULL   |     | NULL    |
+----------+-------------------+-----------+------------+--------+--------+-----+---------+

我现在想将这些值从Field1Field10 插入到表AgeYear(在我的原始表中大约有70 列和120 行)。第一行 (Age / Year, 2010, 2011, ...) 是标题行。 Field1 列是前导列。我想将值保存为以下格式:

+-----------+-----+------+--------+
| SheetName | Age | Year | Value  |
+-----------+-----+------+--------+
| Sheet1    | 0   | 2010 | Value1 |
| Sheet1    | 0   | 2011 | Value2 |
| ...       | ... | ...  | ...    |
| Sheet1    | 0   | 2018 | Value9 |
| Sheet1    | 1   | 2010 | Value1 |
| Sheet1    | 1   | 2011 | Value2 |
| ...       | ... | ...  | ...    |
| Sheet1    | 1   | 2018 | Value9 |
| ...       | ... | ...  | ...    |
+-----------+-----+------+--------+

我尝试了以下查询:

DECLARE @sql NVARCHAR(MAX) =
    ';WITH cte AS
     (
         SELECT i.SheetName,
             ROW_NUMBER() OVER(PARTITION BY i.SheetName ORDER BY i.SheetName) AS rn,
             ' + @columns + ' -- @columns = 'Field1, Field2, Field3, Field4, ...'
         FROM dbo.ImportExcelFile i
         WHERE i.Sheetname LIKE ''Sheet1''
     )
     SELECT SheetName,
            age Age,
            y.[Year]
     FROM cte
     CROSS APPLY
     (
         SELECT Field1 age
         FROM dbo.ImportExcelFile
         WHERE SheetName LIKE ''Sheet1''
         AND ISNUMERIC(Field1) = 1
     ) a (age)
     UNPIVOT
     (
         [Year] FOR [Years] IN (' + @columns + ')
     ) y
     WHERE rn = 1'

EXEC (@sql)

到目前为止,我得到了想要的年龄和年限。我的问题是我不知道如何获得这些值。使用UNPIVOT 我没有得到NULL 的值。相反,它会用相同的值填充整个表,即使它们在源表中是 NULL

你能帮帮我吗?

【问题讨论】:

    标签: sql-server tsql sql-server-2014 unpivot cross-apply


    【解决方案1】:

    也许是另一种方法。这不是动态的,而是在 CROSS APPLY 和 JOIN 的帮助下...

    缺点是您必须定义 70 个字段。

    示例

    ;with cte0 as (
                    Select A.ImportId
                          ,A.SheetName
                          ,Age = A.Field1
                          ,B.*
                     From ImportExcelFile A
                     Cross Apply ( values ('Field2',Field2)
                                         ,('Field3',Field3)
                                         ,('Field10',Field10)
                                 ) B (Item,Value)
    
                  )
         ,cte1 as ( Select * from cte0 where ImportId=1 )
     Select A.SheetName
           ,[Age]   = try_convert(int,A.Age)
           ,[Year]  = try_convert(int,B.Value)
           ,[Value] = A.Value
      From  cte0 A
      Join cte1 B on A.Item=B.Item
      Where A.ImportId>1
    

    退货

    【讨论】:

    • 我找不到任何其他方法,所以我接受了你的答案。永远不会超过 200 个字段,所以我在 while 循环中声明了我的 @columns 变量,如下所示:('Field2', Field2), ('Field3', Field3)... 并在 CROSS APPLY 中使用它作为 VALUES。谢谢!
    • @diiN__________ 很高兴它有帮助。我以为你会变得充满活力。我只是想用一个静态版本来说明。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 2015-07-13
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    相关资源
    最近更新 更多