web-dev-qa-db-ja.com

SQL Server 2016でJSON配列の長さを取得する

SQL Server 2016の新しいJSON_サポートについて知っているので、このデータが連続しているとしましょう

{
  "BaseBoarding": 1,
  "PriceLineStrategy": "PerPersonPerNight",
  "Currency": "EUR",
  "BasePriceLineList": [
    {
      "RoomTypeId": 1,
      "PeriodId": 1,
      "Price": 10.0
    },
    {
      "RoomTypeId": 1,
      "PeriodId": 2,
      "Price": 100.0
    },
    {
      "RoomTypeId": 1,
      "PeriodId": 3,
      "Price": 190.0
    },
    {
      "RoomTypeId": 2,
      "PeriodId": 1,
      "Price": 280.0
    },
    {
      "RoomTypeId": 2,
      "PeriodId": 2,
      "Price": 310.0
    },
    {
      "RoomTypeId": 2,
      "PeriodId": 3,
      "Price": 340.0
    }
  ]
}

できれば組み込みのJSONサポートを使用して、最もパフォーマンスの高い方法で「BasePriceLineList」のアイテム数を取得するにはどうすればよいですか?

このようなものを書く必要があります:

SELECT JSON_ARRLEN(JsonDataCol, '$.BasePriceline') FROM MyTable
WHERE Id = 1

結果として6を取得します。

14
Mihail Shishkov

変数の代わりにテーブルを使用する:

SELECT count(priceLineLists.RoomTypeId)
FROM Mytable
CROSS APPLY OPENJSON (JsonDataCol, N'$.BasePriceLineList')
  WITH (
    RoomTypeId int)
      AS priceLineLists
18
rich kalasky

これをデータセットに変換してから、行を数えることができます。

DECLARE @JSON NVARCHAR(4000) = N'{
  "BaseBoarding": 1,
  "PriceLineStrategy": "PerPersonPerNight",
  "Currency": "EUR",
  "BasePriceLineList": [
    {
      "RoomTypeId": 1,
      "PeriodId": 1,
      "Price": 10.0
    },
    {
      "RoomTypeId": 1,
      "PeriodId": 2,
      "Price": 100.0
    },
    {
      "RoomTypeId": 1,
      "PeriodId": 3,
      "Price": 190.0
    },
    {
      "RoomTypeId": 2,
      "PeriodId": 1,
      "Price": 280.0
    },
    {
      "RoomTypeId": 2,
      "PeriodId": 2,
      "Price": 310.0
    },
    {
      "RoomTypeId": 2,
      "PeriodId": 3,
      "Price": 340.0
    }
  ]
}'

select COUNT(*) 
FROM OPENJSON(@json, N'$.BasePriceLineList')
WITH (RoomTypeID varchar(100) '$.RoomTypeId')
9
dfundako

この基本的な必要性は、アドホックデータレビューを行うときに何度か思い付きました。だから私は先に進んで、これをかなり一般的に行うための小さなスカラー関数を作成しました。組み込まれている仮定がほとんどないため、isnullを使用するか、json_valueを使用して、調査しようとしているネストされた配列を引き出す必要がある場合があります。また、これがパフォーマンスにどのような影響を与えるかは本当にわかりません。一度に数十のレコードでこれを実行するだけで済みました。これを行うためのかなり一般的な方法を探している誰かがここに来た場合に備えて、私が共有すると思いました。

注:関数内でthrowが許可されていなくても、無効なJSON配列で関数がエラーをスローするようにするなど、ハッキングされた2つの「トリック」を使用しました。ゼロによる追加の除算は、暗黙の変換設定が本当にゆるやかで、文字列の戻りが有効であった他の場所で私が使用するパターンがある場合のためです。

create function array_length (@array nvarchar(max))
returns int as begin
  if (@array is null or isjson(@array) != 1
      or left(@array, 1) + right(@array, 1) <> '[]')
    return 'Invalid JSON array provided to array_length' + (1/0)
  return (select count(*) from openjson(@array))
end
4
Brian Jorden