我每天都会生成一个JSON文件。根据源数据的不同,它可以有不同的结构(每个JSON文件中的属性可能更多或更少)。举例来说:文件% 1具有属性:productCode、productType、sellerName、sellerCountry文件2具有所有上述属性,加上sellerState,下一个文件的属性可能比文件2更多或更少
如何将这种JSON文件动态地扁平化为SQL表?
文件1:
[
{
"productCode": "00001",
"productType": "Food",
"sellerDetails": [
{
"sellerName": "Cosco",
"sellerCountry": "UK"
}
]
},
{
"productCode": "00002",
"productType": "Clothing"
}
]
文件2:
[
{
"productCode": "00001",
"productType": "Food",
"sellerDetails": [
{
"sellerName": "Cosco",
"sellerCountry": "UK"
}
]
},
{
"productCode": "00002",
"productType": "Clothing"
},
{
"productCode": "00003",
"productType": "Toy",
"sellerDetails": [
{
"sellerName": "Cosco",
"sellerCountry": "AUS",
"sellerState": "VIC"
}
]
}
]
1条答案
按热度按时间1aaf6o9v1#
可以使用动态SQL生成来动态地执行此操作,但在大多数情况下这不是必需的。
在JSON文件中,如果单个实体的值为
null
,则通常会排除它们的属性。这意味着,尽管输出看起来像是 * 动态的 *,但生成这些文件的系统通常符合标准模式。在这种情况下,有一个最大的结构是可能的,但如果你不知道这个模式,你可以通过比较文件来确定它。一旦你有了一个固定的模式,我们就可以根据这个模式读取所有文件,缺失的属性将被导入一个
null
值。这个输入中的一个复杂因素是
sellerDetails
是一个嵌套数组,在SQL中这是一个新的维度或 table,所以我们需要连接提取根元素属性的结果,这将使数据变平。这在How to use OPENJSON on multiple rows中进行了描述
因此,让我们定义最大模式,假设
sellerDetails
具有3个属性:sellerName
、sellerCountry
、sellerState
。如果您标识了更多的字段,请将它们添加到WITH
声明中。这个小提琴演示了MS SQL Server中的解决方案:http://sqlfiddle.com/#!18/7d5fd/2
我已经将两个输入合并到同一个结果集中,以便您可以比较输出
| productCode| productType|卖家名称|卖家国家|sellerState|
| --|--|--|--|--|
| 00001 |食品|中远|英国|NULL|
| 00002 |服装|NULL| NULL| NULL|
| 00003 |玩具|中远|AUS|维克|
请注意,代码忽略了第一个文件中缺少的
sellerState
,并注入了NULL
更新:
感谢@Charlieface指出我们应该考虑使用
OUTER APPLY OPENJSON (product.sellerDetails)
进行嵌套的OPENJSON
调用。CROSS APPLY
的行为类似于INNER JOIN
,因此在这里使用cross apply会导致删除没有 * 任何 *sellerDetails
记录的product
记录,如本例中的'Clothing'。DISTINCT
也被添加到这个查询中以删除重复的条目,例如产品00002 Clothing
出现在两个文件中。以下是变量声明: