如何使用SQL Server将JSON转换为平面文件(表格)格式?

huangapple go评论53阅读模式
英文:

How do you use SQL Server to convert json to a flat file (table) format?

问题

symbol underlyingprice putCall expdate strike bid ask

AMZN 90.965 PUT 2023-03-17:6 90.0 1.83 1.88
AMZN 90.965 PUT 2023-03-17:6 91.0 2.27 2.36
.

英文:

I am using option chain output from TD Ameritrade and would like to access various values such as bid, ask, etc. and the symbol and price from underlying header.

My problem seems to be the date and strike price are keys and not fixed.

The JSON format looks as follows:

(I couldn't post my question the json text looked like code... not sure how to post that)

The output I desire should look like this:

symbol   underlyingprice    putCall   expdate       strike    bid   ask
-------------------------------------------------------------------------
AMZN     90.965             PUT       2023-03-17:6  90.0      1.83  1.88
AMZN     90.965             PUT       2023-03-17:6  91.0      2.27  2.36
  .

答案1

得分: 1

为了简洁起见,以下代码中的JSON示例要比以前的Stack Overflow问题Parse Nested JSON Data of Share Market Data中提供的JSON要简化得多,该问题似乎也使用了从Ameritrade的Get Open Chain方法返回的数据:

declare @json nvarchar(max) = N'{
    "symbol": "AAPL",
    "underlyingPrice": 132.325,
    "putExpDateMap": {
        "2021-01-08:8": {
            "132.0": [
                {
                    "putCall": "PUT",
                    "bid": 2.4,
                    "ask": 2.43,
                    "strikePrice": 132.0
                }
            ],
            "133.0": [
                {
                    "putCall": "PUT",
                    "bid": 2.93,
                    "ask": 2.95,
                    "strikePrice": 133.0
                }
            ]
        }
    }
}';

通过使用两个公用表达式(CTE)来列举键,该查询的工作原理如下:

  1. putExpDateMapKeys列举日期键,例如:"2021-01-08:8"
  2. 在每个日期键内(因为我假设可能会有多个日期键),strikePriceKeys列举了期权行权价格键,例如:"132.0""133.0"

每个CTE表达式还返回一个JSON路径,然后允许最终调用openjson()来访问putCallbidaskstrikePrice的值。

英文:

In the interests of brevity the JSON in the following code is a much reduced example of the JSON presented in a previous Stack Overflow question, Parse Nested JSON Data of Share Market Data, which also seems to be using data returned from Ameritrade's Get Open Chain method:

declare @json nvarchar(max) = N'{
    "symbol": "AAPL",
    "underlyingPrice": 132.325,
    "putExpDateMap": {
        "2021-01-08:8": {
            "132.0": [
                {
                    "putCall": "PUT",
                    "bid": 2.4,
                    "ask": 2.43,
                    "strikePrice": 132.0
                }
            ],
            "133.0": [
                {
                    "putCall": "PUT",
                    "bid": 2.93,
                    "ask": 2.95,
                    "strikePrice": 133.0
                }
            ]
        }
    }
}';

with putExpDateMapKeys (putExpDate, jsonPath) as (
  select
    [key],
    N'$.putExpDateMap.' + quotename([key], N'"') -- e.g.: '$.putExpDateMap."2021-01-08:8"'
  from openjson(@json, N'$.putExpDateMap')
), strikePriceKeys (putExpDate, jsonPath) as (
  select
    putExpDate,
    N'$.' + quotename(putExpDate, N'"') + N'.' + quotename([key], N'"') -- e.g.: '$."2021-01-08:8"."132.0"'
  from putExpDateMapKeys
  cross apply openjson(@json, jsonPath)
)
select J.symbol, J.underlyingPrice, S.putCall, putExpDate as expdate, S.strikePrice, S.bid, S.ask
from openjson(@json) with (
  symbol nvarchar(4),
  underlyingPrice float,
  putExpDateMap nvarchar(max) as JSON
) J
cross apply strikePriceKeys SPK
outer apply openjson(putExpDateMap, SPK.jsonPath) with (
  putCall nvarchar(4),
  strikePrice float,
  bid float,
  ask float
) S;

Which yields the output:

symbol underlyingPrice putCall expdate strikePrice bid ask
AAPL 132.325 PUT 2021-01-08:8 132 2.4 2.43
AAPL 132.325 PUT 2021-01-08:8 133 2.93 2.95

So how does this query work? The property keys inside putExpDateMap are dynamic so we cannot use a hardcoded JSON path to access their contents. I use two CTE expressions to enumerate the keys:

  1. putExpDateMapKeys enumerates the date keys, e.g.: "2021-01-08:8"
  2. within each date key (since I assume there could be more than one) strikePriceKeys enumerates the strike price keys, e.g.: "132.0" and "133.0"

Each CTE expression also returns a JSON path which then allows the final invocation of openjson() to access the putCall, bid, ask and strikePrice values.

答案2

得分: 0

这是您要翻译的代码部分:

declare @json nvarchar(max) = N'{
    "symbol": "AAPL",
    "underlyingPrice": 132.325,
    "putExpDateMap": {
        "2021-01-08:8": {
            "132.0": [
                {
                    "putCall": "PUT",
                    "bid": 2.4,
                    "ask": 2.43,
                    "strikePrice": 132.0
                }
            ],
            "133.0": [
                {
                    "putCall": "PUT",
                    "bid": 2.93,
                    "ask": 2.95,
                    "strikePrice": 133.0
                }
            ]
        }
    }
}';
select JSON_VALUE(jj, '$.symbol') as symbol
  , JSON_VALUE(jj,'$.underlyingPrice') AS underlyingPrice
  , n.[key] AS date
  , nn.[key] AS strikePrice
  , JSON_VALUE(nn.value, '$[0].putCall') AS pCall
  , JSON_VALUE(nn.value, '$[0].bid') AS bid
  , JSON_VALUE(nn.value, '$[0].ask') AS ask
  , JSON_VALUE(nn.value, '$[0].strikePrice') AS strike
  , nn.value
FROM (
     select @json AS jj
  ) j
CROSS APPLY OPENJSON(jj, '$.putExpDateMap') n
CROSS APPLY OPENJSON(n.value) nn

希望这能帮助您。

英文:

An alternative version to Always Learning's great answer which doesn't use dynamic JSON_VALUE which isn't supported in 2016:

declare @json nvarchar(max) = N'{
    "symbol": "AAPL",
    "underlyingPrice": 132.325,
    "putExpDateMap": {
        "2021-01-08:8": {
            "132.0": [
                {
                    "putCall": "PUT",
                    "bid": 2.4,
                    "ask": 2.43,
                    "strikePrice": 132.0
                }
            ],
            "133.0": [
                {
                    "putCall": "PUT",
                    "bid": 2.93,
                    "ask": 2.95,
                    "strikePrice": 133.0
                }
            ]
        }
    }
}';
select JSON_VALUE(jj, '$.symbol') as symbol
  , JSON_VALUE(jj,'$.underlyingPrice') AS underlyingPrice
  , n.[key] AS date
  , nn.[key] AS strikePrice
  , JSON_VALUE(nn.value, '$[0].putCall') AS pCall
  , JSON_VALUE(nn.value, '$[0].bid') AS bid
  , JSON_VALUE(nn.value, '$[0].ask') AS ask
  , JSON_VALUE(nn.value, '$[0].strikePrice') AS strike
  , nn.value
FROM (
     select @json AS jj
  ) j
CROSS APPLY OPENJSON(jj, '$.putExpDateMap') n
CROSS APPLY OPENJSON(n.value) nn

Here, i'm just shredding every array key and then shredding it's content further down to get the values. I use one assumption, that strikePrice array only contains one row. If not, you can do another level of OPENJSON to get every other row

huangapple
  • 本文由 发表于 2023年3月12日 11:24:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/75710897.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定