如何选择第一行中的值为列名的 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 EnumeratorADO 对象源变量 - 设置为 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 数据集?的主要内容,如果未能解决你的问题,请参考以下文章

如何连续添加起始行和下一行的值

如何复制一个数据框的值为空的字段的列名并创建另一个

如何将 SQL 中的列中的值 PIVOT 到新的列名中,然后在这些 PIVOT 列下列出其他列值?

如何oracle function 返回结果集

sql 查询某列值为 a和b

sql 当中 如何查询某个字段中的值的第几个字符中含有相应的值