如何选择第一行中的值为列名的 SQL 数据集?
Posted
技术标签:
【中文标题】如何选择第一行中的值为列名的 SQL 数据集?【英文标题】:How do I select a SQL dataset where values in the first row are the column names? 【发布时间】:2020-07-09 02:07:18 【问题描述】:我的数据如下所示:
ID RowType Col_1 Col_2 Col_3 ... Col_n
1 HDR FirstName LastName Birthdate
2 DTL Steve Bramblet 1989-01-01
3 DTL Bob Marley 1967-03-12
4 DTL Mickey Mouse 1921-04-25
我想返回一个如下所示的表或数据集:
ID FirstName LastName Birthdate
2 Steve Bramblet 1989-01-01
3 Bob Marley 1967-03-12
4 Mickey Mouse 1921-04-25
其中 n = 255(因此有 255 个 Col_ 字段的限制)
***编辑:HDR 行中的数据是任意的,因此我仅使用 FirstName、LastName、Birthdate 作为示例。这就是为什么我认为它需要是动态 SQL,因为我想要结束的列名将根据 HDR 行中的值而变化。谢谢! ***
如果有一个纯粹的 SQL 解决方案,那就是我所追求的。它将进入 ETL 流程 (SSIS),因此如果一切都失败了,我可以使用脚本任务。
即使我可以返回单行,这也是一个解决方案。我在想可能有这样的动态 sql 解决方案:
select Col_1 as FirstName, Col_2 as LastName, Col_3 as Birthdate
【问题讨论】:
SSIS 数据流需要在设计时设置一个常量列。换句话说,您不能定义列名/类型/计数可以更改的单个数据流。您是否试图获得可以处理一组动态输入和输出的单一数据流? 【参考方案1】:不确定您的第一个数据 sn-p 是否已经在 oracle 表中,但它在 CSV 文件中,那么您可以在加载过程中选择跳过标题。
如果数据已经在表中,那么您可以使用UNION
来获得所需的结果
Select * from table name where rowtype=‘HRD’
union
select * from table name where rowtype=‘DTL’
如果您需要名字等作为列标题,那么您无需执行任何操作。根据您的要求设计目标表列。
【讨论】:
【参考方案2】:抱歉,发布了一个答案,但我完全误解了您在源表中将所需的列标题作为 data。
一个简单的解决方案(尽管它需要更多 IO)是将表数据转储到没有标题的平面文件中,然后将其读回,但这次告诉 SSIS 第一行有标题,并忽略 @987654322 @ 柱子。确保在将数据写入中间文件之前正确排序!
要转储到没有标题的文件,您必须将ColumnNamesInFirstDataRow
设置为false
。在属性窗口中设置它,而不是通过编辑连接。更多信息this thread
如果你有很多数据,这显然是非常低效的。
【讨论】:
【参考方案3】:使用row_number
尝试以下操作。这是demo。
with cte as
(
select
*,
row_number() over (order by id) as rn
from myTable
)
select
ID,
Col_1 as FirstName,
Col_2 as LastName,
Col_3 as Birthdate
from cte
where rn > 1
输出:
| id | firstname | lastname | birthdate |
| --- | --------- | -------- | ---------- |
| 2 | Steve | Bramblet | 1989-01-01 |
| 3 | Bob | Marley | 1967-03-12 |
| 4 | Mickey | Mouse | 1921-04-25 |
【讨论】:
感谢@zealous,但你看到我的编辑了吗?数据只是示例,我需要名称为 HDR 行中的值的列,而不是具体的名字、姓氏和出生日期。我希望我解释正确......【参考方案4】:哦,好吧。有一个纯 SSIS 方法,假设源是一个 SQL 表。在这里,相当粗略。
创建一个类型为 Object
的变量 oColSet,以及 255 个类型为 String
且名称为 sColName_1、sColName_2 ... sColName_255 的变量。
使用select top(1) Col_1, Col_2, ... Col_255 from Src where RowType = 'HDR'
之类的查询创建 SQL 任务,在结果集选项卡上设置任务属性 ResultSet = Full Result Set - 将 Result Name 设置为 0 和 变量名为oColSet
。
添加 ForEach 循环枚举器,将其设置为 ForEach ADO Enumerator
,ADO 对象源变量 - 设置为 oColSet
,枚举模式 = 第一个表中的行。然后,在 Variable Mappings 选项卡上 - 定义为这样的示例 (Variable - Index
) - sColName_1 - 0, sColName_2 - 1, ... sColName_255 - 254。
创建一个类型为String
和变量表达式的变量sSQLQuery
"SELECT Col_1 AS ["+@[User::sColName_1]+"],
Col_2 AS ["+@[User::sColName_2]+"],
...
Col_255 AS ["+@[User::sColName_255]+"]
FROM Src WHERE RowType='DTL'"
在 ForEach 循环中 - 添加您的数据流,在 OLEDB 源中 - 将 数据访问模式 设置为 来自变量的 SQL 命令 并提供变量名称 User::sSQLQuery
。在数据流本身上 - 设置 DelayValidation=true。
此设计的主要思想 - 检索所有列名并将其存储在临时变量中(步骤 2)。然后步骤 3 进行解析并将所有结果放入相应的变量中,第 1 列(第 0 列) - 放入 sColName_1 等。步骤 4 将 SQL 命令定义为表达式,每次读取变量时都会对其进行评估。最后,在 ForEach 循环中(解析完成的地方)——你执行你的数据流。
SSIS 的限制 - 数据类型和列名在运行时应与设计时相同。如果您需要进一步将数据集存储到 SQL 中,请告诉我,以便我调整建议的解决方案。
【讨论】:
以上是关于如何选择第一行中的值为列名的 SQL 数据集?的主要内容,如果未能解决你的问题,请参考以下文章