简体   繁体   English

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

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

I'm working with the set of data at this endpoint: https://db.ygoprodeck.com/api/v7/cardinfo.php我正在处理此端点的数据集: https ://db.ygoprodeck.com/api/v7/cardinfo.php

I need to take this JSON and import it into 2 tables: Cards and Sets .我需要将此 JSON 导入 2 个表中: CardsSets Below is the schema for each table.下面是每个表的架构。

Cards

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

For the Cards table, I can insert any single level data into a table using the code below, but how do I go one level deeper into the linkmarkers node and return the value found into the correct column?对于Cards表,我可以使用下面的代码将任何单级数据插入到表中,但是如何更深入地进入linkmarkers节点并将找到的值返回到正确的列中? For example, for row 8614 in the dataset, the linkmarkers node has only 1 key and its value is "Top", so I would need the script to insert "Top" into the linkmarker_top column and null for all the other linkmarker columns.例如,对于数据集中的第 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)
)

Example output row:示例输出行:

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

Sets

id
set_name
set_code
set_rarity
set_rarity_code

For the Sets table, I want to basically create a table where I relate each id to the card_set where each card came from, but I'm not sure how to do this.对于Sets表,我基本上想创建一个表,在其中将每个id与每张卡来自的card_set相关联,但我不确定如何执行此操作。 So using the first row of the dataset as an example:所以以数据集的第一行为例:

Example output row:示例输出行:

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

For linkmarkers , you can pull it out as a JSON array, then inside a CROSS APPLY you can shred it using OPENJSON and pivot it.对于linkmarkers ,您可以将其作为 JSON 数组拉出,然后在CROSS APPLY中,您可以使用OPENJSON将其切碎并进行旋转。

For the card_sets array, you can CROSS APPLY it from the original cards array, and thereby pull out the cards.id at the same time.对于card_sets数组,你可以从原来的cards数组中CROSS APPLY它,从而同时拉出cards.id This can become the foreign key of your table.这可以成为您表的外键。

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;

Note the following:请注意以下事项:

  • You can do the same thing for the other inner arrays.您可以对其他内部数组执行相同的操作。
  • Use of JSON path to jump straight to $.data .使用 JSON 路径直接跳转到$.data
  • If you need to get the array position you can use OPENJSON without a WITH schema, which gives you the array index of each object.如果您需要获取数组位置,您可以使用不带WITH模式的OPENJSON ,它为您提供每个对象的数组索引。
  • Better choice of data types.更好地选择数据类型。
  • Ideally you would create fixed tables with primary and foreign keys, rather than inserting into # temp tables.理想情况下,您将使用主键和外键创建固定表,而不是插入到#临时表中。

db<>fiddle db<>小提琴

Here is my logic (with javascript) for insert record into card table:这是我将记录插入卡表的逻辑(使用javascript):

  1. Grep all record grep 所有记录
  2. If linkmarkers found, add new field name save the record如果找到linkmarkers ,添加新字段名称保存记录
  3. Insert record插入记录

Sample Code:示例代码:

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()

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

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

相关问题 我如何“加入”但在 MySQL 的表中保持独立? - How do I 'join' but keep things separate in tables in MySQL? 如何在单独的mysql表中搜索字词? - How do I search for term in separate mysql tables? 您如何区分结果? 将一组行分成单独的表? - How do you separate results? Separate a group of rows into separate tables? 如何从 PostgreSQL 1:n 表生成 JSON 文档? - How do I produce a JSON document from PostgreSQL 1:n tables? 如何将提取的Json数据导入数据库 - How do i import the extracted Json data to database 如何在单个Crystal报表中获得两个没有联合键的两个独立表的总和? - How do I get two sums of two separate tables with no joint keys in a single crystal report? 如何将2个单独的临时表的输出合并到单个查询中? - How do I merge the output from 2 separate temp tables into a single query? 如何将两个单独的表中的两列拆分为一个视图中联接的多行? - How do I split two columns in two separate tables into joined multiple rows in a view? 如何从三个单独的表中构建一个事件表,以显示随时间的增量变化? - How do I build an events table from three separate tables showing incremental change over time? 如何分开结果 - How do I separate the results
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM