算术运算符适用于 UInt8,UInt16,UInt32,UInt64,Int8,Int16,Int32,Int64,Float32,Float64 等类型。
plus一样。inf,-inf或nan。-9223372036854775808)除以 -1 时,则抛异常。intDiv相同;modulo相同;toUInt8(-257));Float64类型。Float64类型。 比较运算符始终返回 0 或 1 (UInt8)。
可以比较以下几种类型:
以上每组内的类型均可互相比较,但是不同组的类型间不能进行比较。
逻辑函数可以接受任何数字类型的参数,并返回UInt8类型的 0 或 1。
当向函数传递 0 时,函数将判定为false,任何其他非 0 的值都将被判定为true。
NULL,则结果为NULL。NULL,则结果为NULL。NULL时返回NULL。UInt64,该函数也适用于字符串。step作为增量步长的从start到end-1的整形数字数组;arr中索引为n的元素,n必须是整数类型;arr中是否存在元素elem,如果存在,则返回 1,不存在返回 0。arr2是否是arr1的子集,如果是返回 1,不是返回 0;NULL在数组中作为元素值进行处理。arr2的所有元素是否以相同的顺序存在于arr1中,如果存在返回 1,不存在返回 0。x元素的索引(从 1 开始计算),如果x不存在该数组中则返回 0。x元素的个数。Array[1,2,3,...,length(arr)]。arrayEnumerateUniq([10,20,10,30]) = [1,1,2,1];SELECT
arrayEnumerateUniq(
['1','2','3','1','4','1'],
['2','3','4','2','3','2'],
['2','3','4','3','3','2']
)
[1,1,1,1,1,2]
x添加到数组的末尾;x添加到数组的开头;size的数组;size小于数组的原大小,则数组从右侧截断;size大于数组的原大小,则使用extender值或数组项的数据类型的默认值将数组扩展到右侧。offset表示数组的偏移。正值表示左侧的偏移量,负值表示右侧的缩进量,下标从 1 开始计算;length表示子数组的长度,如果指定负值,则该函数返回[offset,array_length-length],如果省略该值,则该函数返回[offset,the_end_of_array]。SELECT
arraySlice([1,2,3,4,5,6], -1) # [6]
SELECT
arraySlice([1, 2, NULL, 4, 5], 2, 3) # [2,NULL,4]
arr进行升序排序,如果指定了func函数,则排序顺序由func函数的调用结果决定。如果func接受多个参数,那么arraySort函数也将解析与func函数参数相同数量的数组参数。NULL,NaN和Inf的排序顺序:SELECT
arraySort([1, nan, 2, NULL, 3, nan, -4, NULL, inf, -inf])
[-inf,-4,1,2,3,inf,nan,nan,NULL,NULL]
arraySort是高阶函数,可以将lambda函数作为第一个参数传递给它。在这种情况下,排序顺序由lambda函数的调用结果决定,示例:SELECT
arraySort((x) -> -x, [1, 2, 3])
[3,2,1]
lambda函数返回排序键,即[1 -> -1, 2 -> -2, 3 -> -3]。由于arraySort函数按升序对键进行排序,因此结果为[3,2,1]。所以,(x) -> -x lambda函数将排序设置为降序。lambda函数可以接受多个参数。在这种情况下,需要为arraySort传递与lambda参数个数相同的数组。函数使用第一个输入的数组中的元素组成返回结果,使用接下来传入的数组作为排序键。示例:SELECT
arraySort((x, y) -> y, ['hello', 'world'], [2, 1])
["world","hello"]
[2, 1]中定义了第一个数组['hello','world']的相应元素的排序键,即['hello' -> 2,'world' -> 1]。 由于lambda函数中没有使用x,因此源数组中的实际值不会影响结果的顺序。所以,'world'将是结果中的第一个元素,'hello'将是结果中的第二个元素。其他示例:SELECT
arraySort((x, y) -> y, [0, 1, 2], ['c', 'b', 'a']) # [2,1,0]
SELECT
arraySort((x, y) -> - y, [0, 1, 2], [1, 2, 3]) # [2,1,0]
arr数组的元素进行排序。如果指定了func函数,则排序顺序由func函数的调用结果决定。如果func接受多个参数,那么arrayReverseSort函数也将解析与func函数参数相同数量的数组作为参数。具体用法同arraySort一样。arrayReduce('groupUniqArray',arr)。SELECT
arrayJoin([1,2,3])
1
2
3
0,第二个是arr[1]-arr[0]之差等。返回的数组中元素的类型由减法的类型推断规则确定(例如UInt8-UInt8=Int16)。示例:SELECT
arrayDifference([1, 3, 9, -3])
[0,2,6,-12]
SELECT
arrayDistinct([1, 2, 2, 3, 1])
[1,2,3]
SELECT
arrayEnumerateDense([10, 20, 10, 30])
[1,2,1,3]
SELECT
arrayIntersect([1, 2], [1, 3], [1, 4])
[1]
'max'、'sum'中的字符串形式传递,使用带参数的聚合函数时,参数在括号中的函数名称后写明,如:'uniqUpTo(6)'。SELECT
arrayReduce('max', [1, 2, 3]) # 3
SELECT
arrayReduce('maxIf', [3, 5], [1, 0]) # 3
SELECT
arrayReduce('uniqUpTo(3)', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) # 4
arrayReduce(agg_func,arraySlice(arr1,index,length),...)相同的结果;ranges指要聚合的范围应该是元组为元素的数组,其中包含每个索引和长度范围,示例:SELECT
arrayReduceInRanges(
'sum',
[(1, 5), (2, 3), (3, 4), (4, 4)],
[1000000, 200000, 30000, 4000, 500, 60, 7]
)
[1234500,234000,34560,4567]
SELECT
arrayReverse([1, 2, 3])
[3,2,1]
SELECT
flatten([[[1]], [[2], [3]]])
[1,2,3]
SELECT
arrayCompact([1, 1, nan, nan, 2, 3, 3, 3])
[1,nan,2,3]
SELECT
arrayZip(['a', 'b', 'c'], [5, 2, 1])
[('a',5),('b',2),('c',1)]
func函数的原始应用中获得的数组返回给arr数组中的每个元素,示例:SELECT
arrayMap(x -> (x + 2), [1, 2, 3])
[3,4,5]
SELECT
arrayMap(
(x, y, z) -> (x, y, z),
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
)
[(1,4,7),(2,5,8),(3,6,9)]
arr1中的元素的数组,其中func返回的值不是 0,示例:SELECT
arrayFilter(x -> x LIKE '%World%', ['Hello', 'abc World'])
['abc World']
SELECT
arrayFilter(
(i, x) -> x LIKE '%World%',
arrayEnumerate(arr),
['Hello', 'abc World'] AS arr
)
[2]
arr1,如果func返回 0,则用arr1[i-1]替换arr1[i]。arr1的第一个元素不会被替换,示例:SELECT
arrayFill(
x -> not isNull(x),
[1, null, 3, 11, 12, null, null, 5, 6, 14, null, null]
)
[1,1,3,11,12,12,12,5,6,14,14,14]
arr1,如果func返回 0,则用arr1[i+1]替换arr1[i]。arr1的最后一个元素不会被替换,示例:SELECT
arrayReverseFill(
x -> not isNull(x),
[1, null, 3, 11, 12, null, null, 5, 6, 14, null, null]
)
[1,3,3,11,12,5,5,5,6,14,NULL,NULL]
arr1拆分为多个数组。当func返回 0 以外的值时,数组将在元素的左侧拆分。数组不会在第一个元素之前被拆分,示例:SELECT
arraySplit((x, y) -> y, [1, 2, 3, 4, 5], [1, 0, 0, 1, 0])
[[1,2,3],[4,5]]
arr1拆分为多个数组。当func返回 0 以外的值时,数组将在元素的右侧拆分,数组不会在最后一个元素之后被拆分。SELECT
arrayReverseSplit((x, y) -> y, [1, 2, 3, 4, 5], [1, 0, 0, 1, 0])
[[1],[2,3,4],[5]]
SELECT
arrayMin([1, 2, 4]) # 1
SELECT
arrayMin(x -> (- x), [1, 2, 4]) # -4
SELECT
arrayMax([1, 2, 4]) # 4
SELECT
arrayMax(x -> (- x), [1, 2, 4]) # -1
SELECT
arraySum([2, 3]) # 5
SELECT
arraySum(x -> x * x, [2, 3]) # 13
SELECT
arrayAvg([1, 2, 4]) # 2.3333333333333335
SELECT
arrayAvg(x -> (x * x), [2, 4]) # 10
func函数,则数组元素的值在求和之前由该函数转换,示例:SELECT
arrayCumSum([1, 2, 1, 8])
[1,3,4,12]
arrayCumSum相同,返回数组中元素的部分和的数组(运行总和),区别是当返回值包含小于零的值时,将该值替换为零,并以零参数执行后续计算。示例:SELECT
arrayCumSumNonNegative([1, 1, -4, 1])
[1,2,0,1]
SELECT
arrayProduct([1,2,3,4,5,6])
720
Date或DateTime转换为指定的时区。 时区是Date/DateTime类型的属性。 表字段或结果集的列的内部值(秒数)不会更改,列的类型会更改,并且其字符串表示形式也会相应更改。DateTime或者DateTime64数据类型的时区名称。value指类型和时间,类型为DateTime或者DateTime64。Date或DateTime转换为包含年份编号(AD)的UInt16类型的数字。Date或DateTime转换为包含季度编号的UInt8类型的数字。Date或DateTime转换为包含月份编号(1-12)的UInt8类型的数字。Date或DateTime转换为包含一年中的某一天编号的UInt16(1-366)类型的数字。Date或DateTime转换为包含一月中的某一天编号的UInt8(1-31)类型的数字。Date或DateTime转换为包含一周中的某一天编号的UInt8(周一是 1,周日是 7)类型的数字。DateTime转换为包含 24 小时制(0-23)小时数的UInt8数字。DateTime转换为包含一小时中分钟数(0-59)的UInt8数字。DateTime转换为包含一分钟中秒数(0-59)的UInt8数字, 闰秒不计算在内。toUnixTimestamp(datetime):将值转换为UInt32类型的 Unix 时间戳数字;toUnixTimestamp(str, [timezone]):根据时区将输入字符串转换为日期时间,并返回相应的 Unix 时间戳。Date或DateTime向前取整到本年的第一天, 返回Date类型。Date或DateTime向前取整到 ISO 本年的第一天, 返回Date类型。Date或DateTime向前取整到本季度的第一天, 返回Date类型。Date或DateTime向前取整到本月的第一天, 返回Date类型。Date或DateTime向前取整到本周的星期一, 返回Date类型。mode将Date或DateTime向前取整到最近的星期日或星期一,返回Date类型。 mode参数的工作方式与toWeek()的mode参数完全相同,mode默认为 0。DateTime向前取整到今天的开始。DateTime向前取整到当前小时的开始。DateTime向前取整到当前分钟的开始。DateTime向前取整到当前秒数的开始。DateTime以五分钟为单位向前取整到最接近的时间点。DateTime以十五分钟为单位向前取整到最接近的时间点。toStartOf*的所有函数的通用函数。toStartOfInterval(t, INTERVAL 1 year)返回与toStartOfYear(t)相同的结果;toStartOfInterval(t, INTERVAL 1 month)返回与toStartOfMonth(t)相同的结果;toStartOfInterval(t, INTERVAL 1 day)返回与toStartOfDay(t)相同的结果;toStartOfInterval(t, INTERVAL 15 minute)返回与toStartOfFifteenMinutes(t)相同的结果。DateTime中的日期转换为一个固定的日期,同时保留时间部分。Date或DateTime转换为年份的编号,从过去的某个固定时间点开始。Date或DateTime转换为季度的数字,从过去的某个固定时间点开始。Date或DateTime转换为月份的编号,从过去的某个固定时间点开始。Date或DateTime转换为星期数,从过去的某个固定时间点开始。Date或DateTime转换为当天的编号,从过去的某个固定时间点开始。DateTime转换为小时数,从过去的某个固定时间点开始。DateTime转换为分钟数,从过去的某个固定时间点开始。DateTime转换为秒数,从过去的某个固定时间点开始。Date或DateTime转换为包含 ISO 年份的UInt16类型的编号。Date或DateTime转换为包含 ISO 周数的UInt8类型的编号。返回Date或DateTime的周数。两个参数形式可以指定星期是从星期日还是星期一开始,以及返回值应在 0 到 53 还是从 1 到 53 的范围内。如果省略了mode参数,则默认值为 0。 toISOWeek()是一个兼容函数,等效于toWeek(date,3)。
如果包含 1 月 1 日的一周在后一年度中有 4 天或更多天,则为第 1 周,否则它是上一年的最后一周,下周是第 1 周。
下表是mode参数的工作方式:
| Mode | First day of week | Range | Week 1 is the first week … |
|---|---|---|---|
| 0 | Sunday | 0 - 53 | with a Sunday in this year |
| 1 | Monday | 0 - 53 | with 4 or more days this year |
| 2 | Sunday | 1 - 53 | with a Sunday in this year |
| 3 | Monday | 1 - 53 | with 4 or more days this year |
| 4 | Sunday | 0 - 53 | with 4 or more days this year |
| 5 | Monday | 0 - 53 | with a Monday in this year |
| 6 | Sunday | 1 - 53 | with 4 or more days this year |
| 7 | Monday | 1 - 53 | with a Monday in this year |
| 8 | Sunday | 1 - 53 | contains January 1 |
| 9 | Monday | 1 - 53 | contains January 1 |
Date的年和周。 结果中的年份可能因为Date为该年份的第一周和最后一周导致Date的年份不同。mode参数的工作方式与toWeek()的mode参数完全相同,默认为 0;toISOYear()是一个兼容函数,等效于intDiv(toYearWeek(date,3),100)。Date或DateTime按指定的单位向前取整到最接近的时间点;unit可选值:second、minute、hour、day、week、month、quarter、year。unit同date_trunc()一样,对应value的时间单位,示例:SELECT
date_add(YEAR, 3, toDate('2018-01-01'))
2021-01-01
unit对应value的时间单位,类型为String,可选值:microsecond、millisecond、second、minute、hour、day、week、month、quarter、year。unit同date_trunc()一样,对应value的时间单位,示例:SELECT
date_sub(YEAR, 3, toDate('2018-01-01'))
2015-01-01
unit同date_trunc()一样,对应value的时间单位,类型为String,示例:select
timestamp_add(toDate('2018-01-01'), INTERVAL 3 MONTH)
2018-04-01
unit同date_trunc()一样,对应value的时间单位,类型为String,示例:select
timestamp_sub(MONTH, 5, toDateTime('2018-12-18 01:02:03'))
2018-07-18 01:02:03
timezone指定时区。toDate(now())相同。today()-1相同。Date或DateTime转换为包含年份和月份编号的UInt32类型的数字(YYYY*100+MM)。Date或DateTime转换为包含年份和月份编号的UInt32类型的数字(YYYY*10000+MM*100+DD)。Date或DateTime转换为包含年份和月份编号的UInt64类型的数字(YYYY*10000000000+MM*100000000+DD*1000000+hh*10000+mm*100+ss)。Date/DateTime,然后返回Date/DateTime,示例:WITH
toDate('2018-01-01') AS date,
toDateTime('2018-01-01 00:00:00') AS date_time
SELECT
addYears(date, 1) AS add_years_with_date,
addYears(date_time, 1) AS add_years_with_date_time
┌─add_years_with_date─┬─add_years_with_date_time─┐
│ 2019-01-01 │ 2019-01-01 00:00:00 │
└─────────────────────┴──────────────────────────┘
Date/DateTime减去一段时间间隔,然后返回Date/DateTime,示例:WITH
toDate('2019-01-01') AS date,
toDateTime('2019-01-01 00:00:00') AS date_time
SELECT
subtractYears(date, 1) AS subtract_years_with_date,
subtractYears(date_time, 1) AS subtract_years_with_date_time
┌─subtract_years_with_date─┬─subtract_years_with_date_time─┐
│ 2018-01-01 │ 2018-01-01 00:00:00 │
└──────────────────────────┴───────────────────────────────┘
StartTime开始到StartTime+Duration秒内的所有符合size(以秒为单位)步长的时间点。其中size是一个可选参数,默认为 1800。 例如,timeSlots(toDateTime('2012-01-01 12:20:00'), 600) = [toDateTime('2012-01-01 12:00:00'), toDateTime('2012-01-01 12:30:00')],这对于搜索在相应会话中综合浏览量是非常有用的。函数根据给定的格式字符串来格式化时间。格式字符串必须是常量表达式,例如:单个结果列不能有多种格式字符串。
支持的格式修饰符:
| 修饰符 | 描述 | 示例 |
|---|---|---|
| %C | 年除以100并截断为整数(00-99) | 20 |
| %d | 月中的一天,零填充(01-31) | 02 |
| %D | 短MM/DD/YY日期,相当于%m/%d/%y | 01/02/2018 |
| %e | 月中的一天,空格填充( 1-31) | 2 |
| %F | 短YYYY-MM-DD日期,相当于%Y-%m-%d | 2018-01-02 |
| %G | ISO周号的四位数年份格式, 从基于周的年份由ISO 8601定义 标准计算得出,通常仅对%V有用 | 2018 |
| %g | 两位数的年份格式,与ISO 8601一致,四位数表示法的缩写 | 18 |
| %H | 24小时格式(00-23) | 22 |
| %I | 12小时格式(01-12) | 10 |
| %j | 一年中的一天 (001-366) | 002 |
| %m | 月份为十进制数(01-12) | 01 |
| %M | 分钟(00-59) | 33 |
| %n | 换行符(") | |
| %p | AM或PM指定 | PM |
| %Q | 季度(1-4) | 1 |
| %R | 24小时HH:MM时间,相当于%H:%M | 22:33 |
| %S | 秒 (00-59) | 44 |
| %t | 水平制表符(’) | |
| %T | ISO8601时间格式(HH:MM:SS),相当于%H:%M:%S | 22:33:44 |
| %u | ISO8601工作日为数字,星期一为1(1-7) | 2 |
| %V | ISO8601周编号(01-53) | 01 |
| %w | 工作日为十进制数,周日为0(0-6) | 2 |
| %y | 年份,最后两位数字(00-99) | 18 |
| %Y | 年 | 2018 |
| %% | %符号 | % |
示例:
SELECT
formatDateTime(toDate('2010-01-04'), '%g')
10
date_part类型为String,可为 ‘year’, ‘quarter’, ‘month’, ‘week’, ‘dayofyear’, ‘day’, ‘weekday’, ‘hour’, ‘minute’, ‘second’;WITH toDateTime('2021-04-14 11:22:33') AS date_value
SELECT
dateName('year', date_value),
dateName('month', date_value),
dateName('day', date_value)
┌─dateName('year', date_value)─┬─dateName('month', date_value)─┬─dateName('day', date_value)─┐
│ 2021 │ April │ 14 │
└──────────────────────────────┴───────────────────────────────┴─────────────────────────────
toDateTime相同,并返回DateTime类型,示例:SELECT
FROM_UNIXTIME(423543535)
1983-06-04 10:58:55
DateTime,第二个是常量格式字符串,它的作用与formatDateTime相同,并返回String类型,示例:SELECT
FROM_UNIXTIME(1234334543, '%Y-%m-%d %R:%S')
2009-02-11 14:42:23
id键获取dict_name字典中attr_name属性的值。dict_name和attr_name是常量字符串。id必须是UInt64。 如果字典中没有id键,则返回字典描述中指定的默认值。dictGetString()函数相同,但默认值取自函数的最后一个参数。dict_name分层字典,查找child_id键是否位于ancestor_id内(或匹配ancestor_id)。返回UInt8。dict_name分层字典,返回从id开始并沿父元素链继续的字典键数组,返回 Array(UInt64)。id。如果不存在,则返回 0,如果存在,则返回 1。x为一个非复合数据类型的值;NULL返回 1,不为NULL返回 0。isNull()函数作用相反。NULL参数并返回第一个非NULL参数;NULL则返回NULL。NULL,则返回第二个参数的值,否则返回第一个值。NULL,x和y类型必须兼容,否则抛出异常;x。Nullable类型的值;x不为NULL,返回x,如果x为NULL,则返回该类型的默认值。Nullable。UInt32(大端)表示的IPv4的地址,返回相应IPv4的字符串表现形式,格式为A.B.C.D(以点分割的十进制数字)。IPv4NumToString函数相反。如果IPv4地址格式无效,则返回 0。IPv4NumToString类似,但使用xxx替换最后一个字节。FixedString(16)类型的二进制格式的IPv6地址。以文本格式返回此地址的字符串。IPv6映射的IPv4地址以::ffff:111.222.33。例如:SELECT
IPv6NumToString(toFixedString(unhex('2A0206B8000000000000000000000011'), 16)) AS addr
2a02:6b8::11
IPv6NumToString相反。如果IPv6地址格式无效,则返回空字节字符串。 十六进制可以是大写的或小写的。UInt32类型的IPv4地址,返回FixedString(16)类型的IPv6地址。例如:SELECT
IPv6NumToString(IPv4ToIPv6(IPv4StringToNum('192.168.0.1'))) AS addr
::ffff:192.168.0.1
IPv4StringToNum()的别名,它采用字符串形式的IPv4地址并返回IPv4类型的值,该二进制值等于IPv4StringToNum()返回的值。IPv6StringToNum()的别名,它采用字符串形式的IPv6地址并返回IPv6类型的值,该二进制值等于IPv6StringToNum()返回的值。separator拆分成多个子串。separator必须为仅包含一个字符的字符串常量, 返回拆分后的子串的数组;splitByChar相同,但它使用多个字符的字符串作为分隔符。 该字符串必须为非空。separator将数组中列出的字符串拼接起来。separator是一个可选参数:一个常量字符串,默认情况下设置为空字符串。 返回拼接后的字符串。a-z和A-Z中选择连续字节的子字符串,返回子字符串数组;SELECT
alphaTokens('abca1abc')
['abca','abc']
UInt8。 如果字符串包含至少一个字节,则该字符串被视为非空字符串,即使这是一个空格或空字符。 该函数也适用于数组。UInt8。 该函数也适用于数组。UInt64。 该函数也适用于数组。ASCII转换为小写。ASCII转换为大写。pattern格式化其他参数。pattern字符串中包含由大括号{}包围的替换字段。 未被包含在大括号中的任何内容都被视为文本内容,它将原样保留在返回值中。示例:SELECT
format('{1} {0} {0}{1}{1}', 'World', 'Hello')
Hello World WorldHelloHello
offset位置为开头,长度为length的子串。offset从1开始(与标准 SQL 相同)。offset和length参数必须是常量。s字符串非空并且末尾不包含c字符,则将c字符附加到末尾。replacement子串替换haystack中第一次出现的pattern子串(如果存在)。 pattern和replacement必须是常量。replacement子串替换haystack中出现的所有的pattern子串。pattern正则表达式的替换。 pattern可以是任意一个有效的re2正则表达式。 如果存在与pattern正则表达式匹配的匹配项,仅替换第一个匹配项。 模式pattern可以指定为replacement。此模式可以包含替代\0-\9。 替代\0包含了整个正则表达式。替代\1-\9对应于子模式编号。要在模板中使用反斜杠\,请使用\将其转义。 另外还请记住,字符串字面值(literal)需要额外的转义。SELECT DISTINCT
EventDate,
replaceRegexpOne(toString(EventDate), '(\\d{4})-(\\d{2})-(\\d{2})', '\\2/\\3/\\1') AS res
FROM test.hits
LIMIT 7
FORMAT TabSeparated
2014-03-17 03/17/2014
2014-03-18 03/18/2014
2014-03-19 03/19/2014
2014-03-20 03/20/2014
2014-03-21 03/21/2014
2014-03-22 03/22/2014
2014-03-23 03/23/2014
SELECT
replaceRegexpOne('Hello, World!', '.*', '\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0') AS res
Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!Hello, World!
replaceRegexpOne相同,但会替换所有出现的匹配项。例如:SELECT
replaceRegexpAll('Hello, World!', '.', '\\0\\0') AS res
HHeelllloo,, WWoorrlldd!!
SELECT
replaceRegexpAll('Hello, World!', '^', 'here: ') AS res
here: Hello, World!
val最小值对应的arg值。 如果val最小值存在几个不同的arg值,输出遇到的第一个arg值;┌─user─────┬─salary─┐
│ director │ 5000 │
│ manager │ 3000 │
│ worker │ 1000 │
└──────────┴────────┘
SELECT
argMin(user, salary), argMin(tuple(user, salary), salary) FROM salary;
┌─argMin(user, salary)─┬─argMin(tuple(user, salary), salary)─┐
│ worker │ ('worker',1000) │
└──────────────────────┴─────────────────────────────────────┘
val最大值对应的arg值。 如果val最大值存在几个不同的arg值,输出遇到的第一个值。