hive hsql 漏斗模型_数据分析之SQL:常用模型

本文详细介绍了SQL中的各种操作,如case when、内连接与左连接的区别、distinct的使用技巧、order by的注意事项、group by和having的运用,以及SQL优化策略。特别强调了在Hive中实现漏斗模型的关键在于左连接,并讨论了如何利用case when进行多条件统计。此外,还探讨了SQL中的聚合函数在数据分析中的重要作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

b1b611c463074135b33766da34e514fa.png

以下介绍常用的SQL写法:

case when的用法---不管偏不偏,你可能真没见过这种写法

内连接VS左连接---80%的业务代码都与之相关

distinct的用法--你可能真的错怪distinct了

order by的注意事项---order by一般放在主查询后,子查询无效!

group by---新手小白,总是group by时报错!

having--having有时真的很牛逼

topN问题---分组取最大,分组取前几

标准SQL与基于hive的SQL---最常见的区别

不得不知的聚合函数---数据库中的聚合函数真的比excel快很多!

SQL优化--路漫漫其修远兮……

做需求写SQL需要注意的问题---一家之言

case when

1、不同的岗位调不同等级的薪水;

select last_name,job_id,salary,case job_id
                                                 when 'IT_PROG' then 1.1*salary 
                                                 when 'ST_CLERK' then 1.15*salary 
                                                  when 'SA_REP' then 1.2*salary 
                                          else salary 
                                          end 
“zhangngongzi”
from employees;

9b542919b574dcf5daabc6f7049b8bc6.png

2、行列转换之case when

select deptno,sum(clerk) as clerk ,sum(salesman) as salesman ,sum(manager) as manager,sum(analyst) as analyst ,sum(president) as president
from 
(select deptno,case job when 'CLERK' THEN SAL  end as  clerk, case job WHEN 'SALESMAN' THEN SAL  end as salesman, case job WHEN 'MANAGER' THEN SAL  end as manager,
case job WHEN 'ANALYST' THEN SAL   end as analyst, 
case job WHEN 'PRESIDENT' THEN SAL  END as president   FROM EMP ) group by deptno;

顺便提一下SQL语句的执行顺序:from--where---group by--having--select --distinct ---order by --limit

加上多表连接后,执行顺序:先执行子查询,再执行主查询;先对两个表执行笛卡尔乘积--join--where---group by--having--select --distinct ---order by --limit

带Left Join的SQL语句的执行顺序

最终实现的效果:

413641b734c5494009bac725aab55f4e.png

3、当你想得到多个指标的数据,又不想写多条语句,那么case when 可以帮到你:

create table qiuzhiliao as 
    select week_begin_date_id,u_user,
    (case 
        when channel = 'oppokeke' then  'oppokeke'
        when channel = 'huawei' then  'huawei'
        when channel = 'xiaomi' then 'xiaomi'
        when channel = 'yingyongbao' then  'yingyongbao'
        when channel = 'yingyongbaozx' then  'yingyongbaozx'
        when channel = 'AppStore' then  'AppStore'
        when channel = 'baidu' then  'baidu'
        --when channel = '360zhushou' then channel ='360zhushou'
        when channel = 'wandoujia'  then 'wandoujia'
        when channel like 'bdsem%' then 'bdsem'
        when channel like 'sgsem%' then 'sgsem'
        when channel like 'smsem%' then 'smsem'
        else '360zhushou'
        end 
    ) AS channel
    from tmp.qzl_1
    where (channel in ('oppokeke','huawei','xiaomi','yingyongbao','yingyongbaozx','AppStore','baidu','360zhushou','wandoujia')
or channel like 'bdsem%'
or channel like 'sgsem%'
or channel like 'smsem%')


select week_begin_date_id,channel ,count (distinct u_user)
    from qiuzhiliao
group by week_begin_date_id,channel 
order by week_begin_date_id,channel
这样可以将具有相同特征信息的聚成一类,然后统计这类的数据;
case 字段 when 条件 then =case when 字段 =条件 then ;

4、case when完成多条件统计

select zc.stab,
    sum(case when toppop>10000 then 1 else  0 end ) as num_10000,
    --sum(case when toppop>10000 then 1  end ) as num_10000
    sum(case when toppop >1000 then 1 else 0 end) as num_10000
from ZipCensus  zc
group by zc.stab
toppop>10000的计数统计为num_10000,toppop>1000的计数统计为num_1000;---case when 完成多条件统计;上面注释行:当不满足条件时返回null,第一个case when不满足条件时,返回0;通常在计数时,推荐返回值返回数字而不是null!并且在聚合函数中使用case when,适用的函数sum()或max(),avg(),很少情况使用count(distinct ).

内连接VS左连接

内连接:连接键如果匹配上,就连接,没有匹配上,就丢掉!

左连接:以左表为准(左表中的所有数据都会出现),右表匹配主表,匹配上就写入,没匹配上就写null。---因为null的存在,就有了业务上最终的漏斗模型!

以下表格完整解释了左连接与内连接的区别!

27d1e88c36e569786aedd7fb9965c85a.png

11a97cfa3841b65cc1d82b395f76d29d.png

举个例子:

create table tmp.qiuzhiliao as  
select t1.u_user,t1.date_sk
from (
select u_user,date_sk
    from dw.order
    where date_sk between 20190211 and 20190318
    and status in  ('支付成功')
)t1
left join (
    select u_user
    from dw.order
    where date_sk between 20190211 and 20190318
    and status = '退款成功'
)t2
on t1.u_user=t2.u_user
where t2.u_user is null
业务中最常用的模型:主表t1是支付成功的用户(包括先支付成功,然后又退款的用户),t2表是退款成功的用户;通过左连接,并where限制,就可以求出实际付款成功的用户(支付成功-退款成功)

我们什么时候使用内连接了:因为表设计的原因,我们一张表不可能容纳所有的数据项,从io性能角度出发,表维度越大,查询时间越长;所以你想跨表引用字段时,就可以使用内连接!

举个例子:A表有用户,视频,支付类型;B表有视频,视频时长;

你现在想知道:用户看了多久的视频;你就得获取A表的用户,视频名,B表的视频时长。

你就得使用内连接。

表设计中:不是所有的表都有主键,但表之间要发生连接,就一定需要主键;那么没有外键约束的表,称为父表;有外键约束的表称为子表;并且子表的外键就连接在主表的主键上。

主键:非空,唯一约束;主键在一张表中,只有一个!但一个主键可以包括多个字段(联合主键)。

回到本题:A表中的视频就是主键,B表中的视频就是外键!

distinct的用法

1、distinct有去除重复值的效果,但查询字段>=2时,就是对这两个字段联合去重(两个字段同时相同,才会被当作重复值)

2、distinct只能放在首列,否则报错!

3、去除重复值最好用group by,distinct更多时候出现在count(distinct 字段)中用于统计去除重复值的条数。

MySql中distinct的用法 - 苔苔以苔苔以苔 - 博客园

order by 的注意事项

1、order by放在语句的最后,同时执行顺序也是最后。

2、order by放在子查询中会失效,一般放在主查询中最后执行!

61bf80f4d2d8b2b7f4741de66ebf1bd5.png

3bd3dccafac645903dcfcf8089238593.png

又经过其它侧面证明,order by放在主查询中得到的u_user才是我们想要的前30名用户!

group by

1、group by+聚合键;

2、select 后只能出现聚合键,或是聚合函数;不能出现其它的字段,否则报错!

SQL中GROUP BY用法示例

having 有时真的很牛逼

1、having只能跟在group by后,不能单独使用;

2、having是对group by分组后的数据进行筛选判断。

SQL中GROUP BY用法示例

topN问题

1、分组取最大,最小,平均值;group by +聚合函数;但无法得到聚合键之外的数据,这时可以使用关联子查询。

2、求得每组前两名数据;limit+union all

select 课程号,max(成绩) as 最大成绩
from score 
group by 课程号;

分组取最大,但得不到聚合键之外的数据;

select * 
from score as a 
where 成绩 = (
select max(成绩) 
from score as b 
where b.课程号 = a.课程号);

使用关联子查询实现;

9260fb1abb4b6abd812fd750d37e028d.png

每组最大的N条记录

1、先求出最大记录所在的组

2、union连接

select 课程号,max(成绩) as 最大成绩
from score 
group by 课程号;

(select * from score where 课程号 = '0001' order by 成绩  desc limit 2)
union all
(select * from score where 课程号 = '0002' order by 成绩  desc limit 2)
union all
(select * from score where 课程号 = '0003' order by 成绩  desc limit 2);

748fb0fe3300fffd9c1cc61573d69d0b.png

标准SQL与基于hive的SQL

在标准SQL中,我们有以下语句:查询所有课程成绩小于60分学生的学号、姓名

select 学号,姓名
from student
where  学号 in (
select 学号 
from student
where 成绩 < 60
);

在Hive中,in后只能跟字符串;比如in ('huawei','oppo'),不允许出现上述的语法结构!

现在通过内连接,对上述语言进行改写:

select t1.学号,t1.姓名
from (
select 学号,姓名
from student 
)t1
inner join (
      select 学号 
from student
where 成绩 < 60
)t2
on t1.学号=t2.学号

不得不知的聚合函数

1,sum与case when的结合

2,count与case when的结合

使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计:各分数段人数,课程号和课程名称;

只为讲清逻辑,想了解表格结构,具体思路,请点击文末提供的参考文献。
select a.课程号,b.课程名称,
sum(case when 成绩 between 85 and 100 
	 then 1 else 0 end) as '[100-85]',
sum(case when 成绩 >=70 and 成绩<85 
	 then 1 else 0 end) as '[85-70]',
sum(case when 成绩>=60 and 成绩<70  
	 then 1 else 0 end) as '[70-60]',
sum(case when 成绩<60 then 1 else 0 end) as '[<60]'
from score as a right join course as b 
on a.课程号=b.课程号
group by a.课程号,b.课程名称;

接下来给一个企业级别的应用(已经去除敏感信息):基于Hive

--产品路径统计可以这么写
--春节活动入口统计
 SELECT day,
        count(CASE when x2_1.event_key = 'initApp'  then x2_1.u_user ELSE NULL end) as ad_pv,--开屏曝光的pv
        count(DISTINCT CASE when x2_1.event_key = 'initApp'  then x2_1.u_user ELSE NULL end) as ad_uv,--开屏曝光的uv
FROM
    (
        SELECT from_unixtime(unix_timestamp(cast(day as string),'yyyyMMdd'),'yyyy-MM-dd') as day,
               event_key,u_user,status,button,device
        from table
        WHERE from_unixtime(unix_timestamp(cast(day as string),'yyyyMMdd'),'yyyy-MM-dd') BETWEEN '2019-03-28' and date_sub(from_unixtime(unix_timestamp(),'yyyy-MM-dd'),1) --int
            AND
                    --开屏曝光
                    event_key = 'initApp'
group by day 
order by day
这种写法在企业中很常见;统计验证埋点数据是否正常,我们一般将case when 当作if else 使用。

SQL优化

1、Hive sql中多表join时,需要将小表写在左边,hive会将小表数据存放内存中,以实现MR中map join的效果;sparksql中,join时大小表的顺序对执行效率几乎没有影响。sparksql-cache小表实现mapjoin优化性能-云栖社区-阿里云

2、count (*)会返回包含null的行数;count (字段)返回不包括null的行数;

3、spark 支持非等值连接,并且查询速度高于hive;一般先在spark上创建表格,然后再hive中查询并导出查询结果。

……

需要注意的事项

0、SQL语言很笨,有时你以为你要的A,实际上跑数是B;SQL语言又很清晰,只要你的逻辑清楚,就可以得出你想要的数据!

1、内连接无所谓表先后顺序;漏斗模型,谁是最左边的表至关重要!选谁漏斗谁要符合业务!

2、筛选哪个表字段,就限制该表渠道,至于连接的其他表,字段不必限制(防止过紧,实际上限制与不限制可能效果一样)

3、左连接漏斗模型,记住右表有NULL,所以,不能group by 右表字段,计数左表字段!(内连接可以)

3、理清了业务逻辑,再去写SQL开发,在用户行为中想SQL逻辑,想清楚用漏斗还是内连接(二者有时可以替换),连接条件是连接用户,还是设备,连接渠道,还是时间(按日),一个表中哪个字段是定的,哪个字段是变的,是否存在一对多关系(一个假mac对应多个用户)

4、建表时,多用字段,少where限制(where用在查询时限制),这样可以保证少建表。

<think>好的,我现在需要仔细分析用户提供的Python代码,解释其中Hive的作用。首先,用户之前的提问被指出混淆了MySQLHive,所以这次可能希望明确区分。当前代码涉及Hive的操作,需要理清各个部分的功能。 首先,观察代码结构。导入模块包括`impala.dbapi`的connect,以及自定义的`ConvertMySQLToHive`类和设置`dbName`。函数`hive_func`接收SQL语句列表,用转换类将MySQL语句转为HiveQL,然后执行。`hive_execute`负责连接Hive并执行转换后的HiveQL。 接下来,我需要理解每个部分的作用。`ConvertMySQLToHive`类的作用可能是将MySQLSQL语法转换为Hive兼容的语法,因为HiveQL和标准SQL存在差异,比如数据类型、函数名称等。转换后的HiveQL语句通过`hive_execute`执行,这里使用了Impyla库的connect,连接到HiveServer2(端口10086)。这说明代码确实在操作Hive,而不是之前的MySQL。 需要确认Hive在这里的角色。Hive常用于大数据分析,处理存储在HDFS上的数据,使用HiveQL进行查询。用户可能是在将原有的MySQL数据库迁移到Hive,或者需要在Hive中执行转换后的查询以进行分析。代码中的转换步骤是关键,可能涉及表结构迁移或查询适配。 另外,注意到`hive_execute`函数中的连接参数,用户和密码为空,可能Hive配置了无需认证,或测试环境中简化了设置。执行过程中捕获异常并打印,说明代码处理了可能的错误,如语法错误或连接问题。 用户可能想知道这段代码如何利用Hive进行数据处理,以及转换的必要性。需要解释Hive在大数据环境中的优势,比如处理大规模数据集、与Hadoop生态系统的整合,以及HiveQL的特点。 总结:这段代码的核心是将MySQLSQL转换为HiveQL,并通过Hive执行,用于在Hive环境中处理数据。Hive在这里作为数据仓库工具,支持大规模数据分析,而代码的转换和执行步骤帮助用户迁移或适配原有的MySQL查询到Hive平台。</think>以下是对这段代码中Hive作用的详细解析: --- ### 一、代码核心功能 这段代码的核心功能是 **将MySQL语法转换为HiveQL** 并 **在Hive中执行转换后的语句**,主要涉及以下两个关键环节: --- ### 二、Hive的三大核心作用 #### 1. **SQL语法适配** - **问题背景**:MySQLHiveQL存在语法差异(如函数名、数据类型等) - **解决方案**: ```python from util.convert_mysql_to_hive import ConvertMySQLToHive hive_list = cv.convert_mysql_to_hive(sql_str) # 转换MySQL语句为HiveQL ``` - **典型转换示例**: | MySQL语法 | HiveQL语法 | |-------------------------|-------------------------| | `DATETIME` | `TIMESTAMP` | | `ENGINE=InnoDB` | `STORED AS ORC` | | `AUTO_INCREMENT` | 需用分区表替代 | #### 2. **大数据查询执行** - **连接Hive**: ```python conn = connect(host='127.0.0.1', port=10086, # 通过HiveServer2端口连接 user="", password="") # 默认使用HiveServer2的10000端口 ``` - **执行优势**: - 支持分布式计算(通过MapReduce/Tez/Spark引擎) - 直接操作HDFS上的海量数据 - 适合批量数据处理(与MySQL的单条操作形成对比) #### 3. **数据仓库集成** - **典型场景**: - 将MySQL业务数据导入Hive构建数仓 - 在Hive中创建与MySQL结构兼容的表 - 执行复杂分析查询(如窗口函数、多表JOIN) - **代码体现**: ```python cur.execute(hive_sql) # 执行转换后的HiveQL语句 ``` --- ### 三、技术栈关键点解析 | 组件 | 作用说明 | |---------------------|--------------------------------------------------------------------------| | `impala.dbapi` | 通过HiveServer2协议连接Hive(需启动`hiveserver2`服务) | | `ConvertMySQLToHive`| 自定义转换器,处理语法差异(如删除MySQL特有语法,添加Hive存储格式声明) | | 端口`10086` | 自定义HiveServer2服务端口(默认是10000) | --- ### 四、典型应用场景 1. **数据迁移** - 将MySQL表结构自动转换为Hive表定义 - 示例转换结果: ```sql -- MySQL原语句 CREATE TABLE users ( id INT AUTO_INCREMENT, name VARCHAR(255), PRIMARY KEY (id) ) ENGINE=InnoDB; -- 转换后HiveQL CREATE TABLE users ( id INT, name STRING ) STORED AS ORC; ``` 2. **跨库查询** - 在保持业务逻辑不变的前提下,让原有MySQL查询适配Hive执行 3. **数据分析** - 利用Hive的分布式计算能力处理TB级数据 - 执行MySQL无法承载的复杂分析操作 --- ### 五、潜在注意事项 1. **语法覆盖度** - 自定义转换器可能无法处理所有MySQL特性(如事务、存储过程) 2. **性能差异** - Hive适合批量处理,但延迟高于MySQL - 示例:单条`UPDATE`操作在Hive中需要重写为全表覆盖 3. **元数据管理** - 需确保Hive中已存在目标数据库(`dbName`对应的库) 如果需要进一步优化,可考虑结合Hive的以下特性: - 使用分区表提升查询性能 - 采用压缩存储格式(如ORC) - 集成Tez/Spark执行引擎
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值