从 table 中的 table 获取值(逆轴/交叉应用)

Getting values from a table that's inside a table (unpivot / cross apply)

我的其中一个导入 table 遇到严重问题。我已将 Excel 文件导入 SQL 服务器 table。 table 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 插入到 table AgeYear(在我原来的 table 中大约有 70 列和 120 行)。第一行(Age / Year20102011、...)是 header 行。 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 值。相反,它用相同的值填充整个 table,即使它们在源 table.

中是 NULL

你能帮帮我吗?

也许是另一种方法。这不是动态的,而是借助 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

Returns