web-dev-qa-db-ja.com

MySQL:標準SQLクエリからJSONを返す

JSONオブジェクトとJSONオブジェクトタイプについて読みました。選択したいだけで、JSONが返されます。 JSONオブジェクトを保存する必要はありません。シリアライゼーション自体は私の質問ではありません。列は通常のVarchar、Intなどの列で、JSONオブジェクトはなく、「通常の」データベース行です。

通常の古いSELECTを実行してMySQLのJSONを返すことはできますか?

これは、SQL SERVERの FOR JSON およびPostgreSQLの rows_for_json の機能ではありませんか?

彼らはこれで先に見えたが、私は自分を騙したくなかった。

私は2016年からこの質問を見つけました: https://stackoverflow.com/questions/35324795/mysql-5-7-return-row-as-json-using-new-json-features

10
johnny

少し理解しました(PostgreSQLで慣れている場合 mucheasy !)が、細かいことを調べればマニュアル ここ 、_12.16.2 Functions That Create JSON Values_の下に_JSON_ARRAY_関数がありますが、実際にはあまり使用されていません-少なくともこの場合は!

_"select and it return JSON"_の質問に答えるには、これを行う2つの方法があり、どちらもかなり苦痛です!

あなたはどちらか

  • 「ハック」を使用します-db-fiddle here を参照してください、

  • またはここで新しいMySQL提供のJSON関数の1つを使用します-皮肉なことに、これはハック自体よりもハックのようです! MySQLでのみ! :-)(フィドル ここ )。

どちらの回答もMySQLの_GROUP_CONCAT_関数を使用します- この投稿 が役立ちました。 group_concat_max_len システム変数をデフォルト(少し淡い1024)より少し多めに設定したいかもしれません!

最初のクエリは、ご想像のとおり、乱雑です(この回答の最後にあるDDLおよびDML)。

_SELECT CONCAT('[', better_result, ']') AS best_result FROM
(
SELECT GROUP_CONCAT('{', my_json, '}' SEPARATOR ',') AS better_result FROM
(
  SELECT 
    CONCAT
    (
      '"name_field":'   , '"', name_field   , '"', ',' 
      '"address_field":', '"', address_field, '"', ','
      '"contact_age":'  , contact_age
    ) AS my_json
  FROM contact
) AS more_json
) AS yet_more_json;
_

結果:

_[{"name_field":"Mary","address_field":"address one","contact_age":25},{"name_field":"Fred","address_field":"address two","contact_age":35},{"name_field":"Bill","address_field":"address three","contact_age":47}]
_

正解ですが、少し悪夢に立ち向かいましょう!

次に、MySQL JSON_ARRAY()アプローチがあります(これはさらに面倒です-TRANSLATE()関数の(存在しない)実装をMySQLに感謝します!)。

_SELECT
CONCAT
('[', REPLACE
  (
    REPLACE
    (
      GROUP_CONCAT
      (
        JSON_ARRAY
        (
          'name_field:', name_field, 
          'address_field:', address_field, 
          'age_field:', contact_age
        ) SEPARATOR ','
      ), '[', '{'
    ), ']', '}'
  ), ']'
) 
AS best_result2 
FROM contact
_

同じ結果!

_====  TABLE CREATION and INSERT DDL and DML ============

    CREATE TABLE contact
    (
         name_field VARCHAR  (5) NOT NULL,
      address_field VARCHAR (20) NOT NULL,
      contact_age   INTEGER      NOT NULL
    );

    INSERT INTO contact
    VALUES
    ('Mary', 'address one',   25),
    ('Fred', 'address two',   35),
    ('Bill', 'address three', 47);
_
11
Vérace

行をjsonに変換する

JSONを集約したいように聞こえません。 _row_to_json_の同等物が必要だとおっしゃっていますが、そうであれば、はるかに単純な _JSON_OBJECT_ をチェックアウトすることをお勧めします。

_SELECT JSON_OBJECT(
  'name_field', name_field,
  'address_field', address_field,
  'contact_age', contact_age
)
FROM contact;
_

JSONの集約

補足として、結果セットをjsonに集約する必要がある場合。その後、次のMySQL 8がそれを行います。

  • JSON_ARRAYAGG() 結果セットを単一のJSON配列として返します
  • JSON_OBJECTAGG() `結果セットを単一のJSONオブジェクトとして返す
17
Evan Carroll

JSONオブジェクトの配列(クエリの行ごとに1つのオブジェクト)の場合、これを行うことができます。

SELECT JSON_ARRAYAGG(JSON_OBJECT("fieldA", fieldA, "fieldB", fieldB)) 
  FROM table;

すべてのエントリを含む単一のJSON配列になります。

[
  {
    "fieldA": "value",
    "fieldB": "value"
  },
  ...
]

残念ながら、MySQLでは*を使用してすべてのフィールドを選択することはできません。これは素晴らしいことですが、notは機能します:

SELECT JSON_ARRAYAGG(JSON_OBJECT(*)) FROM table;
6
Eneko Alonso

これで同じ答えが得られますが、コードははるかに簡単です。 json_objectgroup_concatother answer を簡略化します。

select 
    concat('[',
        GROUP_CONCAT(
            JSON_OBJECT(    
                'name_field', name_field
                ,'address_field', address_field
                ,'contact_age', contact_age
                )
            SEPARATOR ',')
    ,']')
    from contact;
3
dmelt