如何将具有多个值的列加载到表中的单独行中

Posted

技术标签:

【中文标题】如何将具有多个值的列加载到表中的单独行中【英文标题】:How to load a column with multiple values into separate lines into a table 【发布时间】:2015-05-19 14:12:50 【问题描述】:

我有一个如下所示的 Excel 工作表:

+---------+----------------+
| ItemNum |  Substitutes   |
+---------+----------------+
| ABCD    | XXXX/YYYY/ZZZZ |
| PQRS    | AAAA/BBBB/CCCC |
+---------+----------------+

我需要通过以下方式将其加载到 MS Access 或 SQL Server 中的表中:

+---------+------------+
| ItemNum | Substitute |
+---------+------------+
| ABCD    | XXXX       |
| ABCD    | YYYY       |
| ABCD    | ZZZZ       |
| PQRS    | AAAA       |
| PQRS    | BBBB       |
| PQRS    | CCCC       |
+---------+------------+

请就如何做到这一点提出建议。我知道有一种方法可以使用 Excel VBA 做到这一点。但是我正在寻找无宏的选项,其中可以将文件按原样加载到临时表中,然后使用 SQL 可以以所需的形式获得它。

【问题讨论】:

But I am looking for options that are macro - free 为什么用Excel-VBA 标记它然后:) 我已经删除了标记。如果您对 VBA 持开放态度,请重新添加标签并从您的帖子中删除该行 substitutes 列中的值是否总是 3 个? 另外,这些值总是 4 个字符长还是不同的长度? 【参考方案1】:

按原样导入数据,然后您可以使用此查询将它们拆分:

SELECT T1.ItemNum, T2.mySplits as Substitute
FROM
 (
  SELECT *,
  CAST('<X>'+replace(T.Substitutes,'/','</X><X>')+'</X>' as XML) as my_Xml 
  FROM Table1 T
 ) T1
 CROSS APPLY
 ( 
 SELECT my_Data.D.value('.','varchar(50)') as mySplits
 FROM T1.my_Xml.nodes('X') as my_Data(D)
 ) T2

这是一个 Sql Fiddle:http://sqlfiddle.com/#!6/042da/2

【讨论】:

我喜欢这个答案。它甚至适用于像AAAA1234/BBBBxx/CCCCd//SSSS 这样的奇怪数据输入。它正确地输入了 null 值,并且不关心我的长度或数字,因为它是一个 varchar。 感谢 John 提供了非常强大的解决方案。正如clesiemo3 提到的,它对不同的输入非常灵活。我应该在问题中提到这一点,但尽管名称遵循标准,但我们在数据中有一些异常值。这会很好地处理它们。我想深入了解这个查询。请让我知道在哪里可以了解此查询的工作原理。 嗨,马努斯。我会在这里阅读 BOL:msdn.microsoft.com/en-us/library/ms187339.aspx。它相当深入,并清楚地解释了一切。然后看看各种博客。网上有很多这样的例子。【参考方案2】:

您应该采用临时表方法。因为您为 SQL Server 和 Access 都标记了这个,所以这里有两个选项。

如果您知道代码的长度始终相同,则将数据放入临时表中并使用以下内容提取:

select ItemNum, substring(substitutes, 1, 4) as substitute
from staging
where substitutes is not null
union all
select ItemNum, substring(substitutes, 6, 4) as substitute
from staging
where substitutes like '%/%'
union all
select ItemNum, substring(substitutes, 10, 4) as substitute
from staging
where substitutes like '%/%/%'

等等。这是有意以一种可以轻松修改以在 MS Access 中运行的方式编写的。

第二个选项类似,但在 Excel 中进行旋转。使用 Data --> Text To Columns 将数据拆分为单独的列。然后,将它们加载到包含substitute1 等列的表中。然后,您需要如下查询:

select ItemNum, substitute1 as substitute
from staging
where substitute1 is not null
union all
select ItemNum, substitute2 as substitute
from staging
where substitute2 is not null
union all
select ItemNum, substitute3 as substitute
from staging
where substitute3 is not null

再一次,这个查询是有意编写的与 SQL Server 和 MS Access 兼容。

【讨论】:

谢谢戈登。您的答案对于大多数测试用例来说已经足够了。但是数据中有一些异常值让我选择了 John Bell 的解决方案。【参考方案3】:

您有一个上面的 SQL 查询用于导入,这应该是首选方法。如果您想在工作表中尝试基于公式的解决方案,请尝试此公式对。

      

D2:E2 的公式是,

=OFFSET($A$2, INT((ROW(1:1)-1)/3),0)
=MID(OFFSET($A$2, INT((ROW(1:1)-1)/3), 1), MOD((ROW(1:1)-1)*5+1,15), 4)

根据需要填写。作为一次性解决方案,这可能是可行的。

【讨论】:

感谢 Jeeped 提供的意见。它有效,但我对解决此问题的 SQL 解决方案更感兴趣。

以上是关于如何将具有多个值的列加载到表中的单独行中的主要内容,如果未能解决你的问题,请参考以下文章

如何将具有值的列添加到 Spark Java 中的新数据集?

如何将 Avro 文件加载到具有“时间戳”类型的列的 BigQuery 表中

SQL中Unique约束有啥用啊?

SQL中Unique约束有啥用啊?

(Golang)将数组中的所有行插入到表中

如何使用pyspark将具有多个可能值的Json数组列表转换为数据框中的列