繁体   English   中英

如何将此 JSON 导入 2 个单独的表中?

[英]How do I import this JSON into 2 separate tables?

我正在处理此端点的数据集: https ://db.ygoprodeck.com/api/v7/cardinfo.php

我需要将此 JSON 导入 2 个表中: CardsSets 下面是每个表的架构。

id
name
type
desc
race
archetype
atk
def
ban_tcg
ban_ocg
ban_goat
level
attribute
linkval
image_url
image_url_small
pendulum_scale
linkmarker_topleft --deeper than single level
linkmarker_top --deeper than single level
linkmarker_topright --deeper than single level
linkmarker_left --deeper than single level
linkmarker_right --deeper than single level
linkmarker_bottomleft --deeper than single level
linkmarker_bottom --deeper than single level
linkmarker_bottomright --deeper than single level

对于Cards表,我可以使用下面的代码将任何单级数据插入到表中,但是如何更深入地进入linkmarkers节点并将找到的值返回到正确的列中? 例如,对于数据集中的第 8614 行, linkmarkers节点只有 1 个键,其值为“Top”,因此我需要脚本将“Top”插入到linkmarker_top列中,并将所有其他linkmarker列插入 null。

Declare @JSON varchar(max)
Declare @JSON2 varchar(max)
SELECT @JSON=BulkColumn
FROM OPENROWSET (BULK 'C:\Users\User\Desktop\YGOCards.json', SINGLE_CLOB) import
SELECT @JSON2 = value 
FROM OPENJSON (@JSON)
select * into #cards
from openjson(@JSON2)
with (
    [id] nvarchar(4000)
    , [name] nvarchar(1000)
    , [type] nvarchar(1000)
    , [desc] nvarchar(1000)
    , [race] nvarchar(1000)
    , [archetype] nvarchar(1000)
    , [atk] nvarchar(1000)
    , [def] nvarchar(1000)
    , [ban_tcg] nvarchar(1000)
    , [ban_ocg] nvarchar(1000)
    , [ban_goat] nvarchar(1000)
    , [level] nvarchar(1000)
    , [attribute] nvarchar(1000)
    , [linkval] nvarchar(1000)
)

示例输出行:

id ...   linkmarker_topleft  linkmarker_top  linkmarker_topright  linkmarker_left...
94259633 null                Top             null                 null 

id
set_name
set_code
set_rarity
set_rarity_code

对于Sets表,我基本上想创建一个表,在其中将每个id与每张卡来自的card_set相关联,但我不确定如何执行此操作。 所以以数据集的第一行为例:

示例输出行:

id        set_name              set_code    set_rarity...
34541863  Force of the Breaker  FOTB-EN043  Common

对于linkmarkers ,您可以将其作为 JSON 数组拉出,然后在CROSS APPLY中,您可以使用OPENJSON将其切碎并进行旋转。

对于card_sets数组,你可以从原来的cards数组中CROSS APPLY它,从而同时拉出cards.id 这可以成为您表的外键。

SELECT
  c.*,
  lm.*
INTO #cards
FROM OPENJSON(@json, '$.data')
  WITH (
    [id] int
    , [name] nvarchar(1000)
    , [type] nvarchar(1000)
    , [desc] nvarchar(1000)
    , [race] nvarchar(1000)
    , [archetype] nvarchar(1000)
    , [atk] nvarchar(1000)
    , [def] nvarchar(1000)
    , [ban_tcg] nvarchar(1000)
    , [ban_ocg] nvarchar(1000)
    , [ban_goat] nvarchar(1000)
    , [level] nvarchar(1000)
    , [attribute] nvarchar(1000)
    , [linkval] nvarchar(1000)
    , linkmarkers nvarchar(max) AS JSON
  ) c
CROSS APPLY (
    SELECT
       MIN(CASE WHEN mark.value = 'Top'          THEN 1 END) [Top]
      ,MIN(CASE WHEN mark.value = 'Top-Left'     THEN 1 END) [Top-Left]
      ,MIN(CASE WHEN mark.value = 'Top-Right'    THEN 1 END) [Top-Right]
      ,MIN(CASE WHEN mark.value = 'Bottom'       THEN 1 END) [Bottom]
      ,MIN(CASE WHEN mark.value = 'Bottom-Left'  THEN 1 END) [Bottom-Left]
      ,MIN(CASE WHEN mark.value = 'Bottom-Right' THEN 1 END) [Bottom-Right]
    FROM OPENJSON(c.linkmarkers) mark
) lm;

  
SELECT
  c.id card_id,
  s.*
INTO #sets
FROM OPENJSON(@json, '$.data')
  WITH (
    [id] int,
    card_sets nvarchar(max) AS JSON
  ) c
CROSS APPLY OPENJSON(c.card_sets)
  WITH (
    set_name nvarchar(100),
    set_code nvarchar(10),
    set_rarity nvarchar(100),
    set_rarity_code nvarchar(10)
  ) s;

请注意以下事项:

  • 您可以对其他内部数组执行相同的操作。
  • 使用 JSON 路径直接跳转到$.data
  • 如果您需要获取数组位置,您可以使用不带WITH模式的OPENJSON ,它为您提供每个对象的数组索引。
  • 更好地选择数据类型。
  • 理想情况下,您将使用主键和外键创建固定表,而不是插入到#临时表中。

db<>小提琴

这是我将记录插入卡表的逻辑(使用javascript):

  1. grep 所有记录
  2. 如果找到linkmarkers ,添加新字段名称保存记录
  3. 插入记录

示例代码:

const jp = require('jsonpath')
const source = require("./source.js") // reference from cardinfo.php

async function main() {
  // Cards
  let query = jp.query(source, "$.data[*]")
  query = query.map((x) => {
    if(x.linkmarkers){
      (x.linkmarkers).forEach((y) => {
        console.log(`linkmarker_${y.toLowerCase()}`)
        x[`linkmarker_${y.toLowerCase()}`] = y
      })      
    }
    return x
  })

  // Set Table
  let table = [["id", "nams", "linkmarket_topleft", "linkmarket_top", "linkmarker_bottom"]]
  for(let i=0; i<query.length; i++){
    let { id, name, linkmarket_topleft, linkmarket_top, linkmarker_bottom } = query[i]
    
    // Your insert SQL query
    // ...
  }
}
main()

第 2 点之后的 csv 结果: 在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM