我有一个包含行的表,其中一行有一个包含数据的字段
{"name":"Richard","lastname":null,"city":"Olavarria","cityId":null}
我想选择我所拥有的所有不同的“城市”价值观。仅使用mysql服务器。
有可能吗?我正在尝试这样的事情
SELECT id FROM table_name WHERE field_name REGEXP '"key_name":"([^"]*)key_word([^"]*)"';
但我无法使正则表达式工作
提前致谢
答案 0 :(得分:10)
MySQL在5.7.7版本中支持JSON http://mysqlserverteam.com/json-labs-release-native-json-data-type-and-binary-format/ 您将能够使用jsn_extract函数有效地解析您的JSON字符串。
如果你有一个旧版本并且想要纯粹在mysql中解决它,那么我担心你必须将它作为一个字符串处理并从中减少它的值(只是正常的字符串函数或使用正则表达式) 这不优雅,但它会起作用
http://sqlfiddle.com/#!9/97cfd/14
SELECT
DISTINCT(substring(jsonfield, locate('"city":',jsonfield)+8,
locate('","', jsonfield, locate('"city":',jsonfield))-locate('"city":',jsonfield)-8)
)
FROM
ForgeRock
答案 1 :(得分:4)
我把它包装成一个存储函数,用于那些受限于MySQL< 5.7.7:
的函数CREATE FUNCTION `json_extract_string`(
p_json text,
p_key text
) RETURNS varchar(40) CHARSET latin1
BEGIN
SET @pattern = CONCAT('"', p_key, '":"');
SET @start_i = LOCATE(@pattern, p_json) + CHAR_LENGTH(@pattern);
if @start_i = CHAR_LENGTH(@pattern) then
SET @end_i = 0;
else
SET @end_i = LOCATE('"', p_json, @start_i) - @start_i;
end if;
RETURN SUBSTR(p_json, @start_i, @end_i);
END
请注意,这只适用于字符串值,但比@DmitryK的答案更健壮,因为如果找不到键,它会返回一个空字符串,并且键可以在JSON字符串中的任何位置。
答案 2 :(得分:0)
请参阅MariaDB' Dynamic Columns。
另外,在这个论坛搜索[mysql] [json];这个话题经常被讨论过。
答案 3 :(得分:0)
是的,您绝对可以使用mysql中的JSON_EXTRACT()函数。
让我们获取一个包含JSON的表(此处为表client_services
):
+-----+-----------+--------------------------------------+
| id | client_id | service_values |
+-----+-----------+------------+-------------------------+
| 100 | 1000 | { "quota": 1,"data_transfer":160000} |
| 101 | 1000 | { "quota": 2,"data_transfer":800000} |
| 102 | 1000 | { "quota": 3,"data_transfer":70000} |
| 103 | 1001 | { "quota": 1,"data_transfer":97000} |
| 104 | 1001 | { "quota": 2,"data_transfer":1760} |
| 105 | 1002 | { "quota": 2,"data_transfer":1060} |
+-----+-----------+--------------------------------------+
要选择每个JSON字段,请运行以下查询:
SELECT
id, client_id,
json_extract(service_values, '$.quota') AS quota,
json_extract(service_values, '$.data_transfer') AS data_transfer
FROM client_services;
所以输出将是:
+-----+-----------+----------------------+
| id | client_id | quota | data_transfer|
+-----+-----------+----------------------+
| 100 | 1000 | 1 | 160000 |
| 101 | 1000 | 2 | 800000 |
| 102 | 1000 | 3 | 70000 |
| 103 | 1001 | 1 | 97000 |
| 104 | 1001 | 2 | 1760 |
| 105 | 1002 | 2 | 1060 |
+-----+-----------+----------------------+
现在,如果您想说 DISTINCT 配额,请运行以下查询:
SELECT
distinct( JSON_EXTRACT(service_values, '$.quota')) AS quota
FROM client_services;
所以这将导致您想要的输出:
+-------+
| quota |
+-------+
| 1 |
| 2 |
| 3 |
+-------+
希望这会有所帮助!
答案 4 :(得分:-1)
这可能有点晚了,但是被接受的答案对我不起作用。我用SUBSTRING_INDEX达到了预期的效果。
SELECT
ID, SUBSTRING_INDEX(SUBSTRING_INDEX(JSON, '"mykey" : "', -1), '",', 1) MYKEY
FROM MY_TABLE;
希望这会有所帮助。