导航:首页 > 编程语言 > sql中jsonvalue函数

sql中jsonvalue函数

发布时间:2023-01-25 19:04:37

『壹』 mysql json类型数据 怎么统计指定value值的重复数量

1、mysql专门对json数据提供了相应的访问方式,比如你要的其实就是sum函数;
2、sql代码例如:

1

select sum(data->"$.height") from table_name;

其中的table_name是假设你的表名叫table_name。

『贰』 mysql json类型的一些说明

以前最讨厌英语了,然而没有想到有一天居然要看英文文档学习东西的时候,只想说MMP。下面就是一些学习的东西的记录啦。

之前听小伙伴说他们用的 pgsql ,pgsql 是如何如何牛逼,支持json。然后就去学习了下,但是公司用的是mysql,然后某个项目mysql用了5.7.20版本,这个版本支持json,所以就又学习了一波。吐槽完毕,下面就是正文了。

mysql5.7版本支持json,具体说的是5.7.8开始。这是需要注意的,然后可以的话大家还是看下官方文档吧。

mysql 5.7 josn官方文档地址

我这里 json_content 就定义的是json类型,下面就是基本的操作,后续会写一些json函数。

这算是一个比较复杂的json了,array里面放的是一个数组,other放了另一个对象。下面我再插入几条数据。

下面两条的数据和第一条不一样,是为了做一些说明用。lisi这条数据所有的字段都有,但是数据和张三略有不同,而wangwu这条数据就有些字段没有。

说明下,我原来用的navicat发现查josn的时候是空 select * 的时候定义的json字段会不显示,然后换了新版本就好了。

结果如下:

上面两条sql都是通过json对象中flag=0的数据,然后上面两条sql是等价的。JSON_EXTRACT函数的语法为:JSON_EXTRACT(字段名,‘$.key’),这个函数可以在条件中使用,也可以在查询的时候使用。如下:

结果如下:

嗯哼,没错 JSON_EXTRACT 这个函数是用来获取json对象中指定key的值的。这是一个很常用的函数。
上面既然提到了time,那么就用time来展示下吧。json对象中的时间,可以直接拿来比较,sql如下:

结果如下:

我的条件限定的是 2018-06-05 15:49:00 之后,获取到了2条数据,是不是很神奇呢。这里就要说明下了,这里涉及到了json对象里面对key对应的value进行比较的时候会有一个优先级,mysql会按照这个优先级来转换,然后进行比较,这里只贴一下优先级情况,各个类型的比较的规则自己去文档里面看吧。

下面再介绍两个查询时候会用到的函数JSON_CONTAINS() 和 JSON_CONTAINS_PATH()。

下面就是具体的例子:

结果如下:

结果如下:

结果如下:

结果如下:

用法还是比较简单的,嗯,可能有小伙伴会问我要查询不满足条件的数据呢?很简单,比如上面的sql,修改成:

查询暂时就介绍这么多吧,后续可能会补充,现在介绍下修改。

JSON修改的函数比较多,这里介绍一些应该会常用到的。

id=2的数据结果变为:

id=2的数据结果变为:

说明:假设这里key已经存在,那么本次已经存在的将不会被修改,同时可以添加多个。

id=2的数据结果变为:

id=2的数据结果变为:

说明下,如果指定的key不存在,那么不存在的修改无效,存在的会被修改。

id=2的数据结果变为:

说明下,JSON_SET已经存在的会被修改,不存在的会被增加。

下面介绍一些其他函数。

暂时就写这么多吧,后续再进行补充。本人也是刚开始接触mysql的json,如果有问题请指教~

『叁』 第六章 SQL聚合函数 JSON_ARRAYAGG

创建 JSON 格式值数组的聚合函数。

注:IRIS可用,IRIS之前版本不可用。

JSON_ARRAYAGG 聚合函数返回指定列中值的JSON格式数组。

一个简单的 JSON_ARRAYAGG (或 JSON_ARRAYAGG ALL )返回一个 JSON 数组,其中包含所选行中 string-expr 的所有值。
字符串 -expr 为空字符串 (") 的行由数组中的( " u0000" )表示。
字符串 -expr 为NULL的行不包含在数组中。
如果只有一个字符串 -expr 值,并且是空字符串( " ), JSON_ARRAYAGG 将返回 JSON 数组 ["u0000"] 。
如果所有的 string-expr 值为 NULL , JSON_ARRAYAGG 返回一个空的 JSON 数组 [] 。

JSON_ARRAYAGG DISTINCT 返回一个 JSON 数组,由所选行中 string-expr 的所有不同(唯一)值组成: JSON_ARRAYAGG(DISTINCT col1) 。
NULL 字符串 -expr 不包含在 JSON 数组中。
JSON_ARRAYAGG(DISTINCT BY(col2) col1) 返回一个 JSON 数组,该数组只包含记录中 col2 值是不同的(唯一的)的那些 col1 字段值。
但是请注意,不同的 col2 值可能包含一个单独的 NULL 值。

JSON_ARRAYAGG string-expr 不能是流字段。
指定流字段的结果是 SQLCODE -37 。

默认的 JSON_ARRAYAGG 返回类型是 VARCHAR(8192) 。
这个长度包括 JSON 数组格式化字符以及字段数据字符。
如果预期返回的值将需要大于 8192 ,可以使用 CAST 函数指定一个更大的
返回值
例如 CAST(JSON_ARRAYAGG(value)) AS VARCHAR(12000)) 。
如果实际返回的JSON数组长于 JSON_ARRAYAGG 返回类型长度,IRIS将在返回类型长度处截断JSON数组,而不会发出错误。
因为截断JSON数组会删除其关闭的 ] 字符,这使得返回值无效。

可以使用 %SelectMode 属性为 JSON 数组中的元素指定数据显示值: 0=Logical (默认值), 1=ODBC , 2= display 。
如果 string-expr 包含一个 %List 结构,则元素以ODBC模式表示,用逗号分隔,在逻辑和显示模式中以 %List 格式字符表示,用 转义序列表示。

JSON_ARRAYAGG 函数将表中多行列的值组合成一个包含元素值的 JSON 数组。
因为在计算所有聚合字段之后,查询结果集中应用了一个 ORDER BY 子句,所以 ORDER BY 不能直接影响这个列表中的值序列。
在某些情况下, JSON_ARRAYAGG 结果可能是按顺序出现的,但是不应该依赖于这种顺序。
在给定聚合结果值中列出的值不能显式排序。

下面的嵌入式SQL示例返回一个主机变量,该变量包含示例的 Home_State 列中所有值的 JSON 数组。
以字母 A 开头的人名表:

注意,这个 JSON 数组包含重复的值。

下面的动态SQL示例返回一个主机变量,该变量包含样本的 Home_State 列中所有不同(唯一)值的JSON数组。
以字母 A 开头的人名表:

下面的SQL示例为每个州创建了一个 JSON 数组,其中包含在 Home_City 列中找到的所有值,以及按州列出的这些城市值的计数。
每个 Home_State 行包含该状态的所有 Home_City 值的 JSON 数组。
这些JSON数组可能包含重复的城市名称:

更有用的是一个 JSON 数组的所有不同的值,发现在 Home_City 列为每个州,如下所示的动态SQL示例:

注意,这个示例返回每个州的不同城市名称和总城市名称的整数计数。

下面的动态SQL示例使用 %SelectMode 属性为 DOB 日期字段返回的JSON值数组指定 ODBC 显示模式:

下面的动态SQL示例使用 %FOREACH 关键字。
它为每个不同的 Home_State 返回一行,其中包含该 Home_State 的年龄值的JSON数组。

下面的动态SQL示例使用 %AFTERHAVING 关键字。
它为每个 Home_State 返回一行,其中至少包含一个满足 HAVING 子句条件的 Name 值(以 “M” 开头的名称)。
第一个 JSON_ARRAYAGG 函数返回一个包含该状态所有名称的 JSON 数组。
第二个 JSON_ARRAYAGG 函数返回的 JSON 数组只包含满足 HAVING 子句条件的名称:

『肆』 求一个数据库函数解析json 如下图要求

数据库只是用来存储数据的,为什么不把处理数据的部分放在后台?

在这里你需要了解以下几个知识点。

  1. 在sqlserver 中存储json ,需要用字符串类型进行存储,一般用nvarchar()或 varchar()进行存储。

  2. openJson:打开Json字符串

  3. IsJson:判断一个字符串是不是合法的Json格式。是返回1,否返回0,null返回null。

  4. Json_Value:从Json字符串中提取值。

  5. Json_Query:Json字符串中提取对象或数组。

  6. Json_Modify:更新Json字符串中的属性值,并返回更新的Json字符串


然后参考图片的需求,获取输入key值中的value字段可以得到如下sql语句。

  1. 从JSON中获取输入B的JSON对象

    SELECT JSON_QUERY(json, CONCAT('$.',key)) INTO K_VAL;

  2. 从B的JSON对象中,获取value字段的值

    SELECT JSON_VALUE(K_VAL, '$.value') INTO JSONVALUE;


最终我们的声明的函数大概是:

CREATE FUNCTION PARSEJSON(json VARCHAR(2000), key VARCHAR(200))

RETURNS VARCHAR

BEGIN

declare JSONVALUE VARCHAR;

declare K_VAL VARCHAR;

SELECT JSON_QUERY(json, CONCAT('$.',key)) INTO K_VAL;

SELECT JSON_VALUE(K_VAL, '$.value') INTO JSONVALUE;

return JSONVALUE;

『伍』 sql 处理 json

json的数据json.loads进来以后会变成一个json的对象,你需要自己把python对象中的字段值取出来,拼成sql语句你可以把这个过程封装成一个函数importjsondefsave_json(json_str):obj=json.loads(json_str)sql='insertintotblvalues("%s")'%obj['id']#这里注意编码,要转成数据库的编码格式#blabla

『陆』 sqlserver2008不支持json

sql server2008支持json函数
1。json 转化成数据集合
1)转化用函数
CREATE FUNCTION [dbo].[parseJSON]( @JSON NVARCHAR(MAX))

RETURNS @hierarchy TABL

element_id INT IDENTITY(1, 1) NOT NULL, /* internal surrogate primary key gives the order of parsing and the list order */

sequenceNo [int] NULL, /* the place in the sequence for the element */

parent_ID INT,/* if the element has a parent then it is in this column. The document is the ultimate parent, so you can get the structure from recursing from the document */

Object_ID INT,/* each list or object has an object id. This ties all elements to a parent. Lists are treated as objects here */

NAME NVARCHAR(2000),/* the name of the object */

StringValue NVARCHAR(MAX) NOT NULL,/*the string representation of the value of the element. */

ValueType VARCHAR(10) NOT null /* the declared type of the value represented as a string in StringValue*/

)

AS

BEGIN

DECLARE

@FirstObject INT, --the index of the first open bracket found in the JSON string

@OpenDelimiter INT,--the index of the next open bracket found in the JSON string

@NextOpenDelimiter INT,--the index of subsequent open bracket found in the JSON string

@NextCloseDelimiter INT,--the index of subsequent close bracket found in the JSON string

@Type NVARCHAR(10),--whether it denotes an object or an array

@NextCloseDelimiterChar CHAR(1),--either a '}' or a ']'

@Contents NVARCHAR(MAX), --the unparsed contents of the bracketed expression

@Start INT, --index of the start of the token that you are parsing

@end INT,--index of the end of the token that you are parsing

@param INT,--the parameter at the end of the next Object/Array token

@EndOfName INT,--the index of the start of the parameter at end of Object/Array token

@token NVARCHAR(200),--either a string or object

@value NVARCHAR(MAX), -- the value as a string

@SequenceNo int, -- the sequence number within a list

@name NVARCHAR(200), --the name as a string

@parent_ID INT,--the next parent ID to allocate

@lenJSON INT,--the current length of the JSON String

@characters NCHAR(36),--used to convert hex to decimal

@result BIGINT,--the value of the hex symbol being parsed

@index SMALLINT,--used for parsing the hex value

@Escape INT --the index of the next escape character

DECLARE @Strings TABLE /* in this temporary table we keep all strings, even the names of the elements, since they are 'escaped' in a different way, and may contain, unescaped, brackets denoting objects or lists. These are replaced in the JSON string by tokens representing the string */

(

String_ID INT IDENTITY(1, 1),

StringValue NVARCHAR(MAX)

)

SELECT--initialise the characters to convert hex to ascii

@characters='',

@SequenceNo=0, --set the sequence no. to something sensible.

/* firstly we process all strings. This is done because [{} and ] aren't escaped in strings, which complicates an iterative parse. */

@parent_ID=0;

WHILE 1=1 --forever until there is nothing more to do

BEGIN

SELECT

@start=PATINDEX('%[^a-zA-Z]["]%', @json collate SQL_Latin1_General_CP850_Bin);--next delimited string

IF @start=0 BREAK --no more so drop through the WHILE loop

IF SUBSTRING(@json, @start+1, 1)='"'

BEGIN --Delimited Name

SET @start=@Start+1;

SET @end=PATINDEX('%[^\]["]%', RIGHT(@json, LEN(@json+'|')-@start));

END

IF @end=0 --no end delimiter to last string

BREAK --no more

SELECT @token=SUBSTRING(@json, @start+1, @end-1)

--now put in the escaped control characters

SELECT @token=REPLACE(@token, FROMString, TOString)

FROM

(SELECT

'\"' AS FromString, '"' AS ToString

UNION ALL SELECT '\\', '\'

UNION ALL SELECT '\/', '/'

UNION ALL SELECT '\b', CHAR(08)

UNION ALL SELECT '\f', CHAR(12)

UNION ALL SELECT '\n', CHAR(10)

UNION ALL SELECT '\r', CHAR(13)

UNION ALL SELECT '\t', CHAR(09)

) substitutions

SELECT @result=0, @escape=1

--Begin to take out any hex escape codes

WHILE @escape>0

BEGIN

SELECT @index=0,

--find the next hex escape sequence

@escape=PATINDEX('%\x[0-9a-f][0-9a-f][0-9a-f][0-9a-f]%', @token)

IF @escape>0 --if there is one

BEGIN

WHILE @index<4 --there are always four digits to a \x sequence

BEGIN

SELECT --determine its value

@result=@result+POWER(16, @index)

*(CHARINDEX(SUBSTRING(@token, @escape+2+3-@index, 1),

@characters)-1), @index=@index+1 ;

END

-- and replace the hex sequence by its unicode value

SELECT @token=STUFF(@token, @escape, 6, NCHAR(@result))

END

END

--now store the string away

INSERT INTO @Strings (StringValue) SELECT @token

-- and replace the string with a token

SELECT @JSON=STUFF(@json, @start, @end+1,

'@string'+CONVERT(NVARCHAR(5), @@identity))

END

-- all strings are now removed. Now we find the first leaf.

WHILE 1=1 --forever until there is nothing more to do

BEGIN

SELECT @parent_ID=@parent_ID+1

--find the first object or list by looking for the open bracket

SELECT @FirstObject=PATINDEX('%[{[[]%', @json collate SQL_Latin1_General_CP850_Bin)--object or array

IF @FirstObject = 0 BREAK

IF (SUBSTRING(@json, @FirstObject, 1)='{')

SELECT @NextCloseDelimiterChar='}', @type='object'

ELSE

SELECT @NextCloseDelimiterChar=']', @type='array'

SELECT @OpenDelimiter=@firstObject

WHILE 1=1 --find the innermost object or list...

BEGIN

SELECT

@lenJSON=LEN(@JSON+'|')-1

--find the matching close-delimiter proceeding after the open-delimiter

SELECT

@NextCloseDelimiter=CHARINDEX(@NextCloseDelimiterChar, @json,

@OpenDelimiter+1)

--is there an intervening open-delimiter of either type

SELECT @NextOpenDelimiter=PATINDEX('%[{[[]%',

RIGHT(@json, @lenJSON-@OpenDelimiter)collate SQL_Latin1_General_CP850_Bin)--object

IF @NextOpenDelimiter=0

BREAK

SELECT @NextOpenDelimiter=@NextOpenDelimiter+@OpenDelimiter

IF @NextCloseDelimiter<@NextOpenDelimiter

BREAK

IF SUBSTRING(@json, @NextOpenDelimiter, 1)='{'

SELECT @NextCloseDelimiterChar='}', @type='object'

ELSE

SELECT @NextCloseDelimiterChar=']', @type='array'

SELECT @OpenDelimiter=@NextOpenDelimiter

END

---and parse out the list or name/value pairs

SELECT

@contents=SUBSTRING(@json, @OpenDelimiter+1,

@NextCloseDelimiter-@OpenDelimiter-1)

SELECT

@JSON=STUFF(@json, @OpenDelimiter,

@NextCloseDelimiter-@OpenDelimiter+1,

'@'+@type+CONVERT(NVARCHAR(5), @parent_ID))

WHILE (PATINDEX('%[A-Za-z0-9@+.e]%', @contents collate SQL_Latin1_General_CP850_Bin))<>0

BEGIN

IF @Type='Object' --it will be a 0-n list containing a string followed by a string, number,boolean, or null

BEGIN

SELECT

@SequenceNo=0,@end=CHARINDEX(':', ' '+@contents)--if there is anything, it will be a string-based name.

SELECT @start=PATINDEX('%[^A-Za-z@][@]%', ' '+@contents)--AAAAAAAA

SELECT @token=SUBSTRING(' '+@contents, @start+1, @End-@Start-1),

@endofname=PATINDEX('%[0-9]%', @token collate SQL_Latin1_General_CP850_Bin),

@param=RIGHT(@token, LEN(@token)-@endofname+1)

SELECT

@token=LEFT(@token, @endofname-1),

@Contents=RIGHT(' '+@contents, LEN(' '+@contents+'|')-@end-1)

SELECT @name=stringvalue FROM @strings

WHERE string_id=@param --fetch the name

END

ELSE

SELECT @Name=null,@SequenceNo=@SequenceNo+1

SELECT

@end=CHARINDEX(',', @contents)-- a string-token, object-token, list-token, number,boolean, or null

IF @end=0

SELECT @end=PATINDEX('%[A-Za-z0-9@+.e][^A-Za-z0-9@+.e]%', @Contents+' ')

+1

SELECT

@start=PATINDEX('%[^A-Za-z0-9@+.e][A-Za-z0-9@+.e]%', ' '+@contents)

--select @start,@end, LEN(@contents+'|'), @contents

SELECT

@Value=RTRIM(SUBSTRING(@contents, @start, @End-@Start)),

@Contents=RIGHT(@contents+' ', LEN(@contents+'|')-@end)

IF SUBSTRING(@value, 1, 7)='@object'

INSERT INTO @hierarchy

(NAME, SequenceNo, parent_ID, StringValue, Object_ID, ValueType)

SELECT @name, @SequenceNo, @parent_ID, SUBSTRING(@value, 8, 5),

SUBSTRING(@value, 8, 5), 'object'

ELSE

IF SUBSTRING(@value, 1, 6)='@array'

INSERT INTO @hierarchy

(NAME, SequenceNo, parent_ID, StringValue, Object_ID, ValueType)

SELECT @name, @SequenceNo, @parent_ID, SUBSTRING(@value, 7, 5),

SUBSTRING(@value, 7, 5), 'array'

ELSE

IF SUBSTRING(@value, 1, 7)='@string'

INSERT INTO @hierarchy

(NAME, SequenceNo, parent_ID, StringValue, ValueType)

SELECT @name, @SequenceNo, @parent_ID, stringvalue, 'string'

FROM @strings

WHERE string_id=SUBSTRING(@value, 8, 5)

ELSE

IF @value IN ('true', 'false')

INSERT INTO @hierarchy

(NAME, SequenceNo, parent_ID, StringValue, ValueType)

SELECT @name, @SequenceNo, @parent_ID, @value, 'boolean'

ELSE

IF @value='null'

INSERT INTO @hierarchy

(NAME, SequenceNo, parent_ID, StringValue, ValueType)

SELECT @name, @SequenceNo, @parent_ID, @value, 'null'

ELSE

IF PATINDEX('%[^0-9]%', @value collate SQL_Latin1_General_CP850_Bin)>0

INSERT INTO @hierarchy

(NAME, SequenceNo, parent_ID, StringValue, ValueType)

SELECT @name, @SequenceNo, @parent_ID, @value, 'real'

ELSE

INSERT INTO @hierarchy

(NAME, SequenceNo, parent_ID, StringValue, ValueType)

SELECT @name, @SequenceNo, @parent_ID, @value, 'int'

if @Contents=' ' Select @SequenceNo=0

END

END

INSERT INTO @hierarchy (NAME, SequenceNo, parent_ID, StringValue, Object_ID, ValueType)

SELECT '-',1, NULL, '', @parent_id-1, @type

--

RETURN

END

2.举例

Select * from parseJSON('{
"联系人":
{
"姓名": "huang",
"网名": "HTL",
"AGE": 05,
"男人":true,
"PhoneNumbers":
{
"mobile":"135123100514",
"phone":"0251-123456789"
}

}
}
')

以上用到函数,转自:http://blog.csdn.net/ghlfllz/article/details/51649837#

二、sql转化成json、xml等方法
见链接:http://www.cnblogs.com/huangtailang/p/4277809.html

原文链接:https://www.simple-talk.com/sql/t-sql-programming/consuming-json-strings-in-sql-server/

三、sqlserver2016支持json
请看:https://msdn.microsoft.com/en-us/library/dn921897.aspx

SELECT Name, Surname,
JSON_VALUE(jsonCol, '$.info.address.PostCode') as PostCode,
JSON_VALUE(jsonCol, '$.info.address."Address Line 1"') + ' ' + JSON_VALUE(jsonCol, '$.info.address."Address Line 2"') AS Address,
JSON_QUERY(jsonCol, '$.info.skills') as Skills
FROM PeopleCollection
WHERE ISJSON(jsonCol) > 0
AND JSON_VALUE(jsonCol, '$.info.address.town') = 'Belgrade'
AND Status = 'Active'
ORDER BY JSON_VALUE(@jsonInfo, '$.info.address.PostCode')
文章知识点与官方知识档案匹配
MySQL入门技能树内置函数JSON函数
29106 人正在系统学习中

『柒』 mysql5.7以下怎么解析json

DELIMITER $$

USE `dw`$$

DROP FUNCTION IF EXISTS `fn_Json_getKeyValue`$$

CREATE DEFINER=`data`@`%` FUNCTION `fn_Json_getKeyValue`(
in_JsonArray VARCHAR(4096),#JSON数组字符串
in_Index TINYINT, #JSON对象序号,序号从1开始
in_KeyName VARCHAR(64)#键名
) RETURNS VARCHAR(512) CHARSET utf8
BEGIN
DECLARE vs_return VARCHAR(4096);
DECLARE vs_JsonArray, vs_Json, vs_KeyName VARCHAR(4096);
#declare vs_Json varchar(4096);
DECLARE vi_pos1, vi_pos2 SMALLINT UNSIGNED;

#写监控日志
#insert into dw.t_etl_log(sp_name, title, description)
#values('dw.fn_Json_getKeyValue', '通过Json键名取键值', concat('in_JsonArray=', in_JsonArray));

SET vs_JsonArray = TRIM(in_JsonArray);
SET vs_KeyName = TRIM(in_KeyName);

IF vs_JsonArray = '' OR vs_JsonArray IS NULL
OR vs_KeyName = '' OR vs_KeyName IS NULL
OR in_Index <= 0 OR in_Index IS NULL THEN
SET vs_return = NULL;
ELSE
#去掉方括号
SET vs_JsonArray = REPLACE(REPLACE(vs_JsonArray, '[', ''), ']', '');
#取指定的JSON对象
SET vs_json = SUBSTRING_INDEX(SUBSTRING_INDEX(vs_JsonArray,'}', in_index),'}',-1);

IF vs_json = '' OR vs_json IS NULL THEN
SET vs_return = NULL;
ELSE
SET vs_KeyName = CONCAT('"', vs_KeyName, '":');
SET vi_pos1 = INSTR(vs_json, vs_KeyName);
IF vi_pos1 > 0 THEN
#如果键名存在
SET vi_pos1 = vi_pos1 + CHAR_LENGTH(vs_KeyName);
SET vi_pos2 = LOCATE(',', vs_json, vi_pos1);
IF vi_pos2 = 0 THEN
#最后一个元素没有','分隔符,也没有结束符'}'
SET vi_pos2 = CHAR_LENGTH(vs_json) + 1;
END IF;
SET vs_return = REPLACE(MID(vs_json, vi_pos1, vi_pos2 - vi_pos1), '"', '');
END IF;
END IF;
END IF;

RETURN(vs_return);
END$$

DELIMITER ;

测试: {"old_current_score":"2","new_current_score":"0","old_grade_id":"1","new_grade_id":"1","grade_time":"2016-04-09 00:43:26","grade_upgrade_time":"2017-04-09 00:43:26"}
select fn_Json_getKeyValue(reason,1,'old_grade_id');

『捌』 Hive sql及窗口函数

hive函数:

1、根据指定条件返回结果:case when then else end as

2、基本类型转换:CAST()

3、nvl:处理空字段:三个str时,是否为空可以指定返回不同的值

4、sql通配符: https://www.w3school.com.cn/sql/sql_wildcards.asp

5、count(1)与COUNT(*):返回行数

如果表没有主键,那么count(1)比count(*)快;

如果有主键,那么count(主键,联合主键)比count(*)快;

count(1)跟count(主键)一样,只扫描主键。count(*)跟count(非主键)一样,扫描整个表。明显前者更快一些。

性能问题:

1.任何情况下SELECT COUNT(*) FROM tablename是最优选择,(指没有where的情况);

2.尽量减少SELECT COUNT(*) FROM tablename WHERE COL = ‘value’ 这种查询;

3.杜绝SELECT COUNT(COL) FROM tablename WHERE COL2 = ‘value’ 的出现。

count(expression):查询 is_reply=0 的数量: SELECT COUNT(IF(is_reply=0,1,NULL)) count FROM t_iov_help_feedback;

6、distinct与group by

distinct去重所有distinct之后所有的字段,如果有一个字段值不一致就不作为一条

group by是根据某一字段分组,然后查询出该条数据的所需字段,可以搭配 where max(time)或者Row_Number函数使用,求出最大的一条数据

7、使用with 临时表名 as() 的形式,简单的临时表直接嵌套进sql中,复杂的和需要复用的表写到临时表中,关联的时候先找到关联字段,过滤条件最好在临时表中先过滤后关联

处理json的函数:

split(json_array_string(schools), '\\|\\|') AS schools

get_json_object(school, '$.id') AS school_id,

字符串函数:

1、instr(’源字符串’ , ‘目标字符串’ ,’开始位置’,’第几次出现’)

instr(sourceString,destString,start,appearPosition)

1.sourceString代表源字符串; destString代表要从源字符串中查找的子串;

2.start代表查找的开始位置,这个参数可选的,默认为1;

3.appearPosition代表想从源字符中查找出第几次出现的destString,这个参数也是可选的, 默认为1

4.如果start的值为负数,则代表从右往左进行查找,但是位置数据仍然从左向右计算。

5.返回值为:查找到的字符串的位置。如果没有查找到,返回0。

最简单例子: 在abcd中查找a的位置,从第一个字母开始查,查找第一次出现时的位置

select instr(‘abcd’,’a’,1,1) from al; —1

应用于模糊查询:instr(字段名/列名, ‘查找字段’)

select code,name,dept,occupation from staff where instr(code, ‘001’)> 0;

等同于 select code, name, dept, occupation from staff where code like ‘%001%’ ;

应用于判断包含关系:

select ccn,mas_loc from mas_loc where instr(‘FH,FHH,FHM’,ccn)>0;

等同于 select ccn,mas_loc from mas_loc where ccn in (‘FH’,’FHH’,’FHM’);

2、substr(string A,int start,int len)和 substring(string A,int start,int len),用法一样

substr(time,1,8) 表示将time从第1位开始截取,截取的长度为8位

第一种用法:

substr(string A,int start)和 substring(string A,int start),用法一样

功效:返回字符串A从下标start位置到结尾的字符串

第二种用法:

substr(string A,int start,int len)和 substring(string A,int start,int len),用法一样

功效:返回字符串A从下标start位置开始,长度为len的字符串

3、get_json_object(form_data,'$.学生姓名') as student_name

json_tuple 函数的作用:用来解析json字符串中的多个字段

4、split(full_name, '\\.') [5] AS zq;  取的是数组里的第六个

日期(时间)函数:

1、to_date(event_time) 返回日期部分

2、date_sub:返回当前日期的相对时间

当前日期:select curdate() 

当前日期前一天:select  date_sub(curdate(),interval 1 day)

当前日期后一天:select date_sub(curdate(),interval -1 day)

date_sub(from_unixtime(unix_timestamp(), 'yyyy-MM-dd HH:mm:ss'), 14)  将现在的时间总秒数转为标准格式时间,返回14天之前的时间

时间戳>>>>日期:

from_unixtime(unix_timestamp(), 'yyyy-MM-dd HH:mm:ss') 将现在的时间总秒数转为标准格式时间

from_unixtime(get_json_object(get_json_object(form_data,'$.挽单时间'),'$.$date')/1000) as retain_time

unix_timestamp('2019-08-15 16:40:00','yyyy-MM-dd HH:mm:ss')  --1565858400

日期>>>>时间戳:unix_timestamp()

date_format:yyyy-MM-dd HH:mm:ss 时间转格式化时间

select date_format('2019-10-07 13:24:20', 'yyyyMMdd000000')-- 20191007000000select date_format('2019-10-07', 'yyyyMMdd000000')-- 20191007000000

1.日期比较函数: datediff语法: datediff(string enddate,string startdate) 

返回值: int 

说明: 返回结束日期减去开始日期的天数。 

举例:  hive> select datediff('2016-12-30','2016-12-29');  1

2.日期增加函数: date_add语法: date_add(string startdate, intdays) 

返回值: string 

说明: 返回开始日期startdate增加days天后的日期。 

举例:  hive>select date_add('2016-12-29',10);  2017-01-08

3.日期减少函数: date_sub语法: date_sub (string startdate,int days) 

返回值: string 

说明: 返回开始日期startdate减少days天后的日期。 

举例:  hive>select date_sub('2016-12-29',10);  2016-12-19

4.查询近30天的数据

select * from table where datediff(current_timestamp,create_time)<=30;

create_time 为table里的字段,current_timestamp 返回当前时间 2018-06-01 11:00:00

3、trunc()函数的用法:当前日期的各种第一天,或者对数字进行不四舍五入的截取

日期:

1.select trunc(sysdate) from al  --2011-3-18  今天的日期为2011-3-18

2.select trunc(sysdate, 'mm')   from   al  --2011-3-1    返回当月第一天.

上月1号    trunc(add_months(current_date(),-1),'MM')

3.select trunc(sysdate,'yy') from al  --2011-1-1       返回当年第一天

4.select trunc(sysdate,'dd') from al  --2011-3-18    返回当前年月日

5.select trunc(sysdate,'yyyy') from al  --2011-1-1   返回当年第一天

6.select trunc(sysdate,'d') from al  --2011-3-13 (星期天)返回当前星期的第一天

7.select trunc(sysdate, 'hh') from al   --2011-3-18 14:00:00   当前时间为14:41  

8.select trunc(sysdate, 'mi') from al  --2011-3-18 14:41:00   TRUNC()函数没有秒的精确

数字:TRUNC(number,num_digits) Number 需要截尾取整的数字。Num_digits 的默认值为 0。TRUNC()函数截取时不进行四舍五入

11.select trunc(123.458,1) from al --123.4

12.select trunc(123.458,-1) from al --120

4、round():四舍五入:

select round(1.455, 2)  #结果是:1.46,即四舍五入到十分位,也就是保留两位小数

select round(1.5)  #默认四舍五入到个位,结果是:2

select round(255, -1)  #结果是:260,即四舍五入到十位,此时个位是5会进位

floor():地板数

ceil()天花板数

5、

6.日期转年函数: year语法:   year(string date) 

返回值: int

说明: 返回日期中的年。

举例:

hive>   select year('2011-12-08 10:03:01') from al;

2011

hive>   select year('2012-12-08') fromal;

2012

7.日期转月函数: month语法: month   (string date) 

返回值: int

说明: 返回日期中的月份。

举例:

hive>   select month('2011-12-08 10:03:01') from al;

12

hive>   select month('2011-08-08') fromal;

8

8.日期转天函数: day语法: day   (string date) 

返回值: int

说明: 返回日期中的天。

举例:

hive>   select day('2011-12-08 10:03:01') from al;

8

hive>   select day('2011-12-24') fromal;

24

9.日期转小时函数: hour语法: hour   (string date) 

返回值: int

说明: 返回日期中的小时。

举例:

hive>   select hour('2011-12-08 10:03:01') from al;

10

10.日期转分钟函数: minute语法: minute   (string date) 

返回值: int

说明: 返回日期中的分钟。

举例:

hive>   select minute('2011-12-08 10:03:01') from al;

3

11.日期转秒函数: second语法: second   (string date) 

返回值: int

说明: 返回日期中的秒。

举例:

hive>   select second('2011-12-08 10:03:01') from al;

1

12.日期转周函数: weekofyear语法:   weekofyear (string date) 

返回值: int

说明: 返回日期在当前的周数。

举例:

hive>   select weekofyear('2011-12-08 10:03:01') from al;

49

查看hive表在hdfs中的位置:show create table 表名;

在hive中hive2hive,hive2hdfs:

HDFS、本地、hive -----> Hive:使用 insert into | overwrite、loaddata local inpath "" into table student;

Hive ----> Hdfs、本地:使用:insert overwrite | local

网站访问量统计:

uv:每用户访问次数

ip:每ip(可能很多人)访问次数

PV:是指页面的浏览次数

VV:是指你访问网站的次数

sql:

基本函数:

count、max、min、sum、avg、like、rlike('2%'、'_2%'、%2%'、'[2]')(java正则)

and、or、not、in   

where、group by、having、{ join on 、full join}  、order by(desc降序)

sort by需要与distribut by集合结合使用:

hive (default)> set maprece.job.reces=3;  //先设置rece的数量 

insert overwrite local directory '/opt/mole/datas/distribute-by'

row format delimited fields terminated by '\t'

先按照部门编号分区,再按照员工编号降序排序。

select * from emp distribute by deptno sort by empno desc;

外部表  create external table if not exists dept

分区表:create table dept_partition ( deptno int, dname string, loc string )  partitioned by ( month string )

load data local inpath '/opt/mole/datas/dept.txt' into table default.dept_partition partition(month='201809'); 

 alter table dept_partition add/drop partition(month='201805') ,partition(month='201804');

多分区联合查询:union

select * from dept_partition2 where month='201809' and day='10';

show partitions dept_partition;

desc formatted dept_partition;

二级分区表:create table dept_partition2 ( deptno int, dname string, loc string ) partitioned by (month string, day string) row format delimited fields terminated by '\t';

分桶抽样查询:分区针对的是数据的存储路径;分桶针对的是数据文件

create table stu_buck(id int, name string) clustered by(id) into 4 bucketsrow format delimited fields terminated by '\t';

设置开启分桶与rece为1:

set hive.enforce.bucketing=true;

set maprece.job.reces=-1;

分桶抽样:select * from stu_bucktablesample(bucket x out of y on id);

抽取,桶数/y,x是从哪个桶开始抽取,y越大 抽样数越少,y与抽样数成反比,x必须小于y

给空字段赋值:

如果员工的comm为NULL,则用-1代替或用其他字段代替  :select nvl(comm,-1) from emp;

case when:如何符合记为1,用于统计、分组统计

select dept_id, sum(case sex when '男' then 1 else 0 end) man , sum(case sex when '女' then 1 else 0 end) woman from emp_sex group by dept_id;

用于组合归类汇总(行转列):UDAF:多转一

concat:拼接查询结果

collect_set(col):去重汇总,产生array类型字段,类似于distinct

select t.base, concat_ws('|',collect_set(t.name))   from (select concat_ws(',',xingzuo,blood_type) base,name  from person_info) t group by t.base;

解释:先第一次查询得到一张没有按照(星座血型)分组的表,然后分组,使用collect_set将名字组合成数组,然后使用concat将数组变成字符串

用于拆分数据:(列转行):UDTF:一转多

explode(col):将hive一列中复杂的array或者map结构拆分成多行。

lateral view  侧面显示:用于和UDTF一对多函数搭配使用

用法:lateral view udtf(expression) tablealias as cate

cate:炸开之后的列别名

temptable :临时表表名

解释:用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。

开窗函数:

Row_Number,Rank,Dense_Rank  over:针对统计查询使用

Row_Number:返回从1开始的序列

Rank:生成分组中的排名序号,会在名词s中留下空位。3 3 5

dense_rank:生成分组中的排名序号,不会在名词中留下空位。3 3 4

over:主要是分组排序,搭配窗口函数使用

结果:

SUM、AVG、MIN、MAX、count

preceding:往前

following:往后

current row:当前行

unbounded:unbounded preceding 从前面的起点, unbounded following:到后面的终点

sum:直接使用sum是总的求和,结合over使用可统计至每一行的结果、总的结果、当前行+之前多少行/之后多少行、当前行到往后所有行的求和。

over(rowsbetween 3/current )  当前行到往后所有行的求和

ntile:分片,结合over使用,可以给数据分片,返回分片号

使用场景:统计出排名前百分之或n分之一的数据。

lead,lag,FIRST_VALUE,LAST_VALUE

lag与lead函数可以返回上下行的数据

lead(col,n,dafault) 用于统计窗口内往下第n行值

第一个参数为列名,第二个参数为往下第n行(可选,默认为1),第三个参数为默认值(当往下第n行为NULL时候,取默认值,如不指定,则为NULL)

LAG(col,n,DEFAULT) 用于统计窗口内往上第n行值

第一个参数为列名,第二个参数为往上第n行(可选,默认为1),第三个参数为默认值(当往上第n行为NULL时候,取默认值,如不指定,则为NULL)

使用场景:通常用于统计某用户在某个网页上的停留时间

FIRST_VALUE:取分组内排序后,截止到当前行,第一个值

LAST_VALUE:取分组内排序后,截止到当前行,最后一个值

范围内求和: https://blog.csdn.net/happyrocking/article/details/105369558

cume_dist,percent_rank

–CUME_DIST :小于等于当前值的 行数 / 分组内总行数

–比如,统计小于等于当前薪水的人数,占总人数的比例

percent_rank:分组内当前行的RANK值-1/分组内总行数-1

总结:

在Spark中使用spark sql与hql一致,也可以直接使用sparkAPI实现。

HiveSql窗口函数主要应用于求TopN,分组排序TopN、TopN求和,前多少名前百分之几。

与Flink窗口函数不同。

Flink中的窗口是用于将无线数据流切分为有限块处理的手段。

window分类:

CountWindow:按照指定的数据条数生成一个 Window,与时间无关。

TimeWindow:按照时间生成 Window。

1. 滚动窗口(Tumbling Windows):时间对齐,窗口长度固定,不重叠::常用于时间段内的聚合计算

2.滑动窗口(Sliding Windows):时间对齐,窗口长度固定,可以有重叠::适用于一段时间内的统计(某接口最近 5min 的失败率来报警)

3. 会话窗口(Session Windows)无时间对齐,无长度,不重叠::设置session间隔,超过时间间隔则窗口关闭。

『玖』 刚入职的菜鸟,在plsql中怎么拼接json字段

Oracle 12.1.0.2版本有一个新功能就是可以存储、查询、索引JSON数据格式,而且也实现了使用SQL语句来解析JSON,非常方便。JSON数据在数据库中以VARCHAR2, CLOB或者BLOB进行存储。Oracle建议用户在插入JSON数据之前,使用is_json来验证输入JSON数据的正确性。另外,Oracle也提供了相关的函数:
Functions:json_value, json_query, json_table.

Conditions:json_exists, is json, is not json, json_textcontains.

『拾』 如何将JSON,Text,XML,CSV 数据文件导入 MySQL

将外部数据导入(import)数据库是在数据库应用中一个很常见的需求。其实这就是在数据的管理和操作中的ETL (Extract, transform, load)的L (Load)部分,也就是说,将特定结构(structure)或者格式(format)的数据导入某个目的地(比如数据库,这里我们讨论MySQL)。

ETL Process

本文要讨论的内容,是如何方便地将多种格式(JSON, Text, XML, CSV)的数据导入MySQL之中。

本文大纲:

将Text文件(包括CSV文件)导入MySQL
将XML文件导入MySQL
将JSON文件导入MySQL
使用MySQL workbench的Table Data Export and Import Wizard进行JSON或CSV文件的导入导出

1. 将Text文件(包括CSV文件)导入MySQL

这里我们的讨论是基于一个假定,Text file和CSV file是有着比较规范的格式的(properly formatted),比如说每行的每个数据域(field)之间是由一个共同的分隔符(比如tab: \t)分隔的。

那么首先,你需要根据你的数据的格式(有哪些域),来设计好数据库的对应的表 (的Schema)。

举个例子,要处理的Text文件或者CSV文件是以\t作为分隔符的,每行有id, name, balance这么三个数据域,那么首先我们需要在数据库中创建这个表:

CREATE TABLE sometable(id INT, name VARCHAR(255), balance DECIMAL(8,4));

创建成功以后就可以导入了。操作方式很简单:

LOAD DATA LOCAL INFILE '你的文件路径(如~/file.csv)' INTO TABLE sometable FIELDS TERMINATED BY '\t' [ENCLOSED BY '"'(可选)] LINES TERMINATED BY '\n' (id, name, balance)

这里要注意的是,我们需要开启local-infile这个MySQL的配置参数,才能够成功导入。究其原因,从MySQL的Manual中可以看到这么一段话:

LOCAL works only if your server and your client both have been configured to permit it. For example, if mysqld was started with --local-infile=0, LOCAL does not work. See Section 6.1.6, “Security Issues with LOAD DATA LOCAL”.

这是MySQL出于安全考虑的默认配置。因此,我们需要在配置文件my.cnf中(以Debian发行版的Linux, 如Ubuntu为例, 即是在/etc/my.cnf中),确保:

local-infile=1

抑或是在命令行启动MySQL时加上--local-infile这一项:

mysql --local-infile -uroot -pyourpwd yourdbname

此外,我们也可以使用MySQL的一个官方导入程序mysqlimport ,这个程序本质上就是为LOAD DATA FILE提供了一个命令行的interface,很容易理解,我们这里就不再详述。

2. 将XML文件导入MySQL

这件事的完成方式,与我们的XML的形式有着很大的关系。

举个例子说,当你的XML数据文件有着很非常规范的格式,比如:
<?xml version="1.0"?>
<row>
<field name="id">1</field>
<field name="name">Free</field>
<field name="balance">2333.3333</field>
</row>

<row>
<field name="id">2</field>
<field name="name">Niki</field>
<field name="balance">1289.2333</field>
</row>

或者
<row column1="value1" column2="value2" .../>

我们就可以很方便使用LOAD XML来导入,这里可以参见MySQL的官方手册--LOAD XML Syntax。

然而我们可能有另外一些需求,比如说,我们可能会想要将XML文件的域映射到不同名字的列(TABLE COLUMN)之中。这里要注意,MySQL v5.0.7以后,MySQL的Stored Procere中不能再运行LOAD XML INFILE 或者LOAD DATA INFILE。所以转换的程序(procere)的编写方式与在此之前有所不同。这里,我们需要使用Load_File()和ExtractValue()这两个函数。

以下是一个示例XML文件和程序:
文件:
<?xml version="1.0"?>
<some_list>
<someone id="1" fname="Rob" lname="Gravelle"/>
<someone id="2" fname="Al" lname="Bundy"/>
<someone id="3" fname="Little" lname="Richard"/>
</some_list>

程序:
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `import_some_xml`(path varchar(255), node varchar(255))
BEGIN
declare xml_content text;
declare v_row_index int unsigned default 0;
declare v_row_count int unsigned;
declare v_xpath_row varchar(255);

set xml_content = load_file(path);

-- calculate the number of row elements.
set v_row_count = extractValue(xml_content, concat('count(', node, ')'));

-- loop through all the row elements
while v_row_index < v_row_count do
set v_row_index = v_row_index + 1;
set v_xpath_row = concat(node, '[', v_row_index, ']/@*');
insert into applicants values (
extractValue(xml_content, concat(v_xpath_row, '[1]')),
extractValue(xml_content, concat(v_xpath_row, '[2]')),
extractValue(xml_content, concat(v_xpath_row, '[3]'))
);
end while;
END

在MySQL中,使用它进行导入:

call import_some_xml('你的XML文件路径', '/some_list/someone');

程序相当的直白,只要了解一下MySQL的脚本编写即可。

这里提一下DELIMITER $$。我们知道MySQL的命令分隔符默认为分号,然而脚本中很显然是有分号的,但是我们并不希望立即执行,所以我们需要临时更改分隔符。

3. 将JSON文件导入MySQL

如何将JSON文件导入MySQL中,是一个很有趣的话题。JSON是一种现在相当常用的文件结构,所以掌握它的导入具有比较广泛的意义。

很多时候,我们处理的JSON数据是以如下形式出现的:
{"name":"Julia","gender":"female"}
{"name":"Alice","gender":"female"}
{"name":"Bob","gender":"male"}
{"name":"Julian","gender":"male"}

而并不是规整的[{},{},{},{}](一些NoSQL数据库的Export)。

这样的形势对于载入有一个好处:因为每一行是一个JSON Object,所以我们便可以按行处理此文件,而不需要因为JSON的严格结构将整个文件(比如一个许多G的.json文件)全部载入。

方式一 使用common-schema

common-schema是一个应用很广泛的MySQL的框架,它有着很丰富的功能和详细的文档。我们可以使用它的JSON解析的功能。(它还具有JSON转换成XML等等方便的功能)

具体说来,将common-schema导入之后,使用它的extract_json_value函数即可。源码中:
create function extract_json_value(
json_text text charset utf8,
xpath text charset utf8
) returns text charset utf8

该函数接受两个参数,一个是json_text,表示json文件的内容,另一个是xpath,表示数据的结构(这里可以类比XML文件的处理)。很多读者应该知道,XPath是用来对XML中的元素进行定位的,这里也可以作一样的理解。

以本段开始的几行JSON为例,这里common-schema的使用如下例:
select common_schema.extract_json_value(f.event_data,'/name') as name, common_schema.extract_json_value(f.event_data,'/gender') as gender, sum(f.event_count) as event_count from json_event_fact f group by name, gender;

关于event_data,我们需要先理解LOAD DATA INFILE是一个event,不同的event type对应不同的event data。这部分知识可以参看Event Data for Specific Event Types

如果感兴趣,可以参看其源码。参看一个受到广泛使用的项目的源码,对于自身成长是很有益的。

当然了,我们也可以像之前处理XML文件导入一样,自己编写程序。这里便不再给出实例程序,有兴趣的读者可以自行编写或者跟笔者交流。

方式二 使用mysqljsonimport

这是Anders Karlsson的一个完成度很高的作品。这一份程序由C写成。它依赖于一个JSON Parser,Jansson。他们都有着比较好的维护和文档,所以使用上体验很好。

mysqljsonimport的下载在SourceForge上。具体使用参照其文档即可。

为了方便不熟悉源码安装的朋友,笔者在这里提一下安装流程和注意事项。
安装命令顺序如下:
$ wget http://sourceforge.net/projects/mysqljson/files/myjsonimport_1.6/mysqljsonimport-1.6.tar.gz
$ tar xvfz mysqljsonimport-1.6.tar.gz
$ cd mysqljsonimport-1.6
$ ./configure –-with-mysql=/xxx/mysql
$ make
$ make check
$ sudo make install

--with-mysql这一步不是必要的,只要你安装的mysql的路径是系统的默认路径。很关键的,而且很容易被不熟悉的朋友忽略的是,这一个C程序要成功编译和运行,是需要MySQL的C API的,所以需要安装的依赖,除了jansson,还有libmysqlclient-dev。

jansson的安装就是简单的源码安装,libmysqlclient-dev则可以使用包管理工具(比如ubuntu中使用apt-get即可;编译和安装前,建议先sudo apt-get update以避免不必要的麻烦)。

导入命令:
$ ./mysqljsonimport –-database test –-table tablename jsonfilename

还有一个parser,作者是Kazuho,感兴趣的读者可以参看一下,他的相关博文是mysql_json - a MySQL UDF for parsing JSON ,github项目是mysql_json。

4. 使用MySQL workbench

Workbench这个工具对于许多不熟悉SQL语言或者命令行的朋友还是很方便和友好的。利用它,可以方便地导入和导出CSV和JSON文件。

具体操作图例参见MySQL官方手册即可:Table Data Export and Import Wizard,这里不再赘述。

文/freenik(简书作者)
原文链接:http://www.jianshu.com/p/d330edb61fe2

阅读全文

与sql中jsonvalue函数相关的资料

热点内容
ipa里资源文件 浏览:110
苹果的文件管理在那里 浏览:633
qq浏览器文件如何发到qq 浏览:736
百度地图加载多个点代码 浏览:146
数据横向复制如何纵向粘贴 浏览:433
2020cab画图数据怎么调 浏览:534
teamview12linux 浏览:175
java编辑word文件 浏览:149
类似scihub的网站有哪些 浏览:398
ios哪里找小众app 浏览:377
毒霸新闻弹窗是哪个文件 浏览:331
雨林木win10 浏览:881
写好的代码怎么编程小程序 浏览:945
改文件属性软件 浏览:917
linux网卡重启新命令 浏览:216
win10升级工具下 浏览:935
电脑qq怎么传文件到手机qq 浏览:417
被360隔离的文件在哪个文件夹 浏览:971
骷髅教程图 浏览:954
ps淘宝女包修图教程 浏览:568

友情链接