Hive SQL中如何判断某个设备属于新设备?


=Start=

缘由:

简单记录一下最近在工作中用到的Hive SQL的知识点,方便以后参考。

正文:

参考解答:
  1. 将表中的一行(但包含多个字段的)数据转换成多行(每行只有一个字段的)数据;
    使用 lateral view explode 进行切分,如果字段中包含特殊字符,需要提前用字符串相关函数进行处理以满足要求
lateral view explode(split(replace(replace(replace(ip_addr, '[', ''), '\"', ''),']',''),',')) ip_addr as ip
  1. explode 函数接收的参数类型是 array/map 类型的
explode(ARRAY<T> a)
explode(MAP<Tkey,Tvalue> m)
  1. collect_set 函数生成的返回值是 array 类型的
  2. array_contains 函数用于判断array中是否存在某个值,返回的是 boolean 类型的 true/false
array_contains(Array<T>, value)
Returns TRUE if the array contains value.
  1. 在已有 group by 的基础上可以通过 partition by 来进行独立的 group by ,可以按需使用
select
username
,ip,device_id
,collect_set(device_id) over (partition by username) device_list
from
...
where
...
group by username,ip,device_id
;

在 group by k1,k2,k3 里面的 collect_set(device) over (partition by k1) device_list 是独立的,可以理解 device_list 是只基于 k1 的 group by ,不受外层的 group by 影响;
在 group by k1,k2,k3 里面的 collect_set(device) as device_list2 是基于外层 k1,k2,k3 的 group by ,如果外层的 group by 条件只有1个且和 partition by 的字段相同,两者的结果就是相同的,否则是不一样的,需要按需根据场景来选择。

  1. to_json 函数
# 通过 to_json 和 map 将多个字段拼接成一个json格式的字符串,方便传递给程序做处理

SELECT
TO_JSON(
map(
"k1", 0,
"k2", "a string",
"k3", "[4, 5, 6]",
"k4", "7890"
)
)
;

==

对于安全来说,很多事件中的异常行为其实可以简单定义为——和之前/其它人不一样,因此就可以通过把之前的数据做一个汇总,统计出前段时间的【常用设备列表/……】,然后再拿当前的记录和统计出的列表做一个比对,如果当前的这个不在常用的设备、职场、认证方式里面,则认为是异常,需要发出告警,由运营人员跟进确认,并进行记录。

新设备、首次访问域名等【首次】的判断逻辑在于——今天(dt)使用的设备、访问的域名,没有在昨天及以前的n天(dt-n,dt-1)中出现过。可以

  1. 将今天使用的设备、访问的域名按自己的聚合需求做一个 group by 去重和统计
  2. 用前段时间的数据用基于 group by 的 collect_set 生成一个历史设备列表、访问域名列表

方法一:3-1. 然后将上面2步生成的临时表基于 username 做 inner join ,然后用 array_contains 判断今天使用的设备、访问的域名在不在上一步生成的列表里面,如果不在的话,说明设备是新设备、域名是近期首次访问的域名,可以发出提醒,然后由运营同学进行跟进确认。

方法二:3-2. 也可以基于 username,device 做 left outer join 当 x2.username is not NULL and x2.device is NULL 时,则可认为是该用户的新设备,后续处理步骤和上面写的一样。

# 方法一
select
x1.*, x2.*
from
(select
username, ip, device, domain
,count(1) as cnt
from
accesslog
where
dt = 'today'
group by username, ip, device, domain
)x1
join
(select
username
,collect_set(device) over (partition by username) device_list
,collect_set(device) as device_list2
,collect_set(domain) over (partition by username) domain_list
,count(1) as cnt
from
accesslog
where
dt between 'today-30' and 'today-1'
group by username
)x2
on x1.username = x2.username
where
! array_contains(x2.device_list, x1.device)
;
# 方法二
select
x1.*, x2.*
from
(select
username, ip, device, domain
,count(1) as cnt
from
accesslog
where
dt = 'today'
group by username, ip, device, domain
)x1
left outer join
(select
username, device
from
accesslog
where
dt between 'today-30' and 'today-1'
group by username, device
)x2
on x1.username = x2.username and x1.device = x2.device
where
x2.username is not NULL and x2.device is NULL
;
参考链接:

LanguageManual UDF
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF#LanguageManualUDF-StringFunctions

Hive–map/string→json&处理Json数据的函数
https://blog.csdn.net/qq_46893497/article/details/109959763

hive查询结果转为json格式
https://blog.csdn.net/weixin_40873462/article/details/98175571

hive 将hive表数据查询出来转为json对象和json数组输出
https://www.cnblogs.com/yfb918/p/11325969.html

Spark SQL和Hive中的函数(二):JSON函数
https://zhuanlan.zhihu.com/p/343758768

=END=


《 “Hive SQL中如何判断某个设备属于新设备?” 》 有 5 条评论

  1. `
    统计时的一些常见维度:

    1、当天的情况(user/operation/target/…)
    2、最近30天(不包含当天)的情况sum(以及user/operation/target是否为首次出现)
    3、最近30天(不包含当天)的情况max(看看近期的峰值情况并做个对比)
    `

  2. Hive中是否存在比较 array 的函数?
    Are there any Hive array comparison functions/udf’s
    https://stackoverflow.com/questions/39329663/are-there-any-hive-array-comparison-functions-udfs
    `
    Arrays are ordered structures,

    concat_ws( $separator , $array )
    this function will join all the array elements into a string using the separator.

    Hive中的array是有序的结构,如果想比较2个array的内容是否完全相同,可以先借助 concat_ws 函数将array类型变量转换成 string 类型的变量然后进行比较。
    如果 array 是你在统计的时候生成的,可能需要提前用 sort_array 对内容排个序然后再转换成string进行比较。

    还有一种思路是,直接比较 array 类型变量中的特定位置的元素(比如用下标0代表第1个),如果不相等,那这2个array肯定就是不相等的,但反过来没有那么直接和绝对(除非比较了array大小和array中的每一个元素)。

    select *
    from arraydemo as a1
    inner join arraydemo as a2
    on a1.arrayCol[0] = a2.arrayCol[0];
    `

  3. Hive 编程专题之 SQL Join 的那点坑
    https://zhuanlan.zhihu.com/p/50445227
    `
    错误类型: 编译错误
    错误关键字: Cartesian products are disabled for safety reasons
    可能原因: 查询产生了笛卡尔积

    【详细错误信息】
    FAILED: SemanticException Cartesian products are disabled for safety reasons. If you know what you are doing, please sethive.strict.checks.cartesian.product to false and that hive.mapred.mode is not set to ‘strict’ to proceed. Note that if you may get errors or incorrect results if you make a mistake while using some of the unsafe features.

    解决方案:
    笛卡尔积:所有key都一对一关联,会导致数据量膨胀巨大,甚至运行不出结果。一般是由于on条件没有写对的原因(比如恒等true),建议检查on的join条件。或者是not in的查询,请使用left join filter is null的方式替换。如果确实需要笛卡尔积的查询,请设置参数

    set hive.strict.checks.cartesian.product=false;
    set hive.mapred.mode=nonstrict;

    原因说明:
    为了保障整个集群的稳定性,类似非全等的 Join (在on条件那里不都是相等的判断条件)是默认禁止的,原因在异常代码中给出了:

    FAILED: SemanticException Cartesian products are disabled for safety reasons

    这样就可以避免因为大数据的 Join 导致网络瘫痪。

    如果清晰的知道,非全等 Join 不会造成影响,那么可以修改这些配置来启动非全等 join 的操作。
    `
    (详细)解决hive报错FAILED: SemanticException Cartesian products are disabled for safety的问题
    https://blog.csdn.net/u014454538/article/details/83794278

    第十章 Hive调优 【严格模式】
    https://www.cnblogs.com/bajiaotai/p/15890034.html

  4. hive array_except
    https://juejin.cn/s/hive%20array_except
    `
    # Hive 官方并没有提供 array_except 这个函数,需要自己写UDF来实现。但是在 GitHub 仓库里有一个 GenericUDFArrayExcept 的UDF样例可以参考一下。

    Hive ARRAY_EXCEPT 是 Hive 中的一个内置函数,它可以在两个数组之间执行差集操作。它返回一个新的数组,其中包含了第一个数组中不存在于第二个数组中的元素。

    语法如下:
    ARRAY array_except(ARRAY a1, ARRAY a2)

    其中,a1 和 a2 是需要进行差集操作的两个数组,而 T 是数组元素的数据类型。

    示例:
    select array_except(array(1, 2, 3), array(2, 3, 4)) as result;

    结果:
    [1]
    `

    hive udf函数 array_except 实现
    https://blog.csdn.net/qq_35515661/article/details/130161544

    数组函数和运算符
    https://www.alibabacloud.com/help/zh/sls/user-guide/array-functions-and-operators

    复杂类型函数
    https://help.aliyun.com/zh/maxcompute/user-guide/complex-type-functions#section-e0m-o6l-r0k

    spark sql 函数 array_except(arr1,arr2)能否确保arr1中原有元素的顺序
    https://blog.csdn.net/qq_35515661/article/details/130141316

    GenericUDFArrayExcept.java
    https://github.com/apache/hive/blob/master/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFArrayExcept.java#L38

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注