# 代替のデータ型

Data Shaping Query Languageでは、Avroスキーマを使い、同じエレメントに対して複数のデータ型を扱うことができます。 Avroスキーマの詳細は、[Oracleのドキュメンテーション](https://docs.oracle.com/cd/E26161_02/html/GettingStartedGuide/avroschemas.html)をご覧ください。

次のサンプルJSON入力では、order\_amountというエレメントは次のいずれかとなります:

* 整数
* 10進数
* 文字列
* 2つの小数値(items\_totalとtax\_amount)が含まれているレコード

```
{
    "orders": [
        {
            "order_id": "abc-12345",
            "order_amount": 250
        },
        {
            "order_id": "def-67890",
            "order_amount": "299.99"
        },
        {
            "order_id": "ghi-54321",
            "order_amount": 435.95
        },
        {
            "order_id": "jkl-09876",
            "order_amount": {
                "items_total": 395.99,
                "tax_amount": 11.89
            }
        }
    ]
}
```

この入力は次のAvroスキーマで記述されます:

```
{
    "type": "record",
    "name": "root",
    "fields": [
        {
            "name": "orders",
            "type": {
                "type": "array",
                "items": {
                    "type": "record",
                    "name": "order",
                    "fields": [
                        {
                            "name": "order_id",
                            "type": "string"
                        },
                        {
                            "name": "order_amount",
                            "type": [
                                "int",
                                {
                                    "type": "bytes",
                                    "logicalType": "decimal"
                                },
                                "string",
                                {
                                    "type": "record",
                                    "name": "amount",
                                    "fields": [
                                        {
                                            "name": "items_total",
                                            "type": {
                                                "type": "bytes",
                                                "logicalType": "decimal"
                                            }
                                        },
                                        {
                                            "name": "tax_amount",
                                            "type": {
                                                "type": "bytes",
                                                "logicalType": "decimal"
                                            }
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            }
        }
    ]
}
```

Data Shaping Query Languageでは、identifier.@indexという構文を使い、エレメントの識別子に型のインデックスを付加することで、それぞれの可能な型を参照できます。この例では、intはorder\_amountエレメントで可能な型のリストの最初の値なので、order\_amount.@0で参照できます。

この構文は階層識別子でも使用できます。たとえば、order\_amount.@3.tax\_amountを使ってレコード内のtax\_amountエレメントを参照できます。

resolveChoiceファンクションを使用すれば、それぞれの反復やエレメントに使用される型を識別できます。このファンクションの詳細は、[特別ファンクション](https://help.qlik.com/talend/ja-JP/data-shaping-language-reference-guide/8.0/special-functions)をご覧ください。

この例では、次のクエリーを使い、orders配列の各項目でorder\_amountエレメントに使用されているデータ型を取得できます:

```
FROM orders
SELECT {
    order_id,
    amount = resolveChoice(order_amount)
}
```

このクエリーは次の結果を返します:

```
[
    {
        "order_id": "abc-12345",
        "amount_type": 0
    },
    {
        "order_id": "def-67890",
        "amount_type": 2
    },
    {
        "order_id": "ghi-54321",
        "amount_type": 1
    },
    {
        "order_id": "jkl-09876",
        "amount_type": 3
    }
]
```

次に、データを調整し、order\_amountエレメントで単一のデータ型を返すクエリーを書くことができます。たとえば次のクエリーを使用できます:

* スイッチ式とresolveChoiceファンクションを使って、それぞれの代替インデックスにデータ型を割り当てます。
* toDecimalファンクションを使って、文字列と整数値を小数に変換します。
* items\_totalにtax\_amountを加え、各レコードの合計金額を計算します。

```
FROM orders
LET $amount_type = 
    SWITCH (resolveChoice(order_amount)) { 
		CASE 0: 'INT' 
		CASE 1: 'DECIMAL' 
		CASE 2: 'STRING' 
		CASE 3: 'RECORD' 
	}
SELECT {
    order_id,
    amount = 
        IF ($amount_type = "STRING" OR $amount_type = "INT") 
            toDecimal(order_amount)
        ELSEIF ($amount_type = "RECORD")
            order_amount.@3.items_total + order_amount.@3.tax_amount
        ELSE order_amount
}
```

このクエリーでは、order\_amountの反復はそれぞれ入力タイプに関係なく10進値に変換されます。以下の結果が返されます:

```
[
    {
        "order_id": "abc-12345",
        "amount": 250
    },
    {
        "order_id": "def-67890",
        "amount": 299.99
    },
    {
        "order_id": "ghi-54321",
        "amount": 435.95
    },
    {
        "order_id": "jkl-09876",
        "amount": 407.88
    }
]
```