横扫SQL面试——PV、UV问题

📊 横扫SQL面试:UV/PV问题

在这里插入图片描述

🌟 什么是UV/PV?

在数据领域,UV(Unique Visitor,独立访客)PV(Page View,页面访问量) 是最基础也最重要的指标:

  • 👥 UV:统计时间段内的唯一用户数(按用户ID去重)
  • 📄 PV:统计时间段内的总访问次数(不去重)

🏆 UV/PV问题为什么重要?

  1. 业务价值:直接反映网站/APP的用户规模和活跃度

  2. 面试高频:90%的数据岗位面试都会涉及,掌握后能轻松应对留存率、转化率等复杂指标

  3. 异常分析:UV突然下降可能原因(渠道故障/数据丢失等)

  4. 衍生指标

    • 人均PV = PV / UV
    • 访问深度 = PV / 会话数
    • 跳出率 = 只访问一页的会话 / 总会话数

🚀 实战练习

1.计算每日uv、pv
访问记录表access_log,包含字段id(自增主键)、user_id(用户ID)、access_date(访问日期)、page_id(页面ID)。

  • 计算出每天的UV和PV。

在这里插入图片描述

  • 计算出某个特定页面(假设页面ID为100)的UV和PV。

在这里插入图片描述

  • 计算每个用户最近7天的平均PV

在这里插入图片描述


2. 对比新老用户的PV贡献占比

用户访问日志表user_visits,包含字段:user_id(用户ID),visit_time(访问时间),page_url(访问页面)。

用户信息表users,包含字段:user_id(用户ID),register_date(注册日期)。

  • 区分新用户(注册后7天内访问)和老用户(注册7天后访问)
  • 计算新老用户各自的PV总量

在这里插入图片描述
在这里插入图片描述

  • 计算新老用户PV占总PV的比例

在这里插入图片描述
最终查询也可:

在这里插入图片描述

完整代码:

-- 第一步:创建CTE (Common Table Expression) 计算每个访问记录的用户类型
WITH user_visit_stats AS (SELECT v.user_id,           -- 用户IDv.visit_time,        -- 访问时间u.register_date,     -- 注册日期CASE -- 判断用户类型:注册后7天内访问的为新用户,否则为老用户WHEN DATEDIFF(v.visit_time, u.register_date) <= 7 THEN '新用户'ELSE '老用户'END AS user_type     -- 用户类型标记FROM user_visits v       -- 访问记录表JOIN users u ON v.user_id = u.user_id  -- 关联用户信息表
),-- 第二步:按用户类型分组统计PV总量
pv_summary AS (SELECT user_type,          -- 用户类型COUNT(*) AS pv_count -- 计算每种用户类型的PV总量FROM user_visit_stats   -- 使用上一步的结果GROUP BY user_type      -- 按用户类型分组
),-- 第三步:计算所有用户的总PV量
total_pv AS (SELECT SUM(pv_count) AS total  -- 汇总所有PVFROM pv_summary                -- 使用上一步的分组统计结果
)-- 最终查询:计算每种用户类型的PV占比
SELECT p.user_type,p.pv_count,ROUND(p.pv_count * 100.0 / (SELECT SUM(pv_count) FROM pv_summary), 2) AS pv_percentage
FROM pv_summary p
ORDER BY p.pv_count DESC;SELECT p.user_type,                   -- 用户类型p.pv_count,                    -- 该类型的PV数量ROUND(p.pv_count * 100.0 / t.total, 2) AS pv_percentage  -- 计算占比(百分比)
FROM pv_summary p                  -- 用户类型分组统计
CROSS JOIN total_pv t              -- 与总PV量交叉连接(确保每行都能计算占比)
ORDER BY p.pv_count DESC;          -- 按PV数量降序排列

  • 计算每日新老用户的PV占比趋势

在这里插入图片描述
在这里插入图片描述

完整代码:

-- 第一步:创建CTE标记每日每条访问记录的用户类型
WITH daily_user_types AS (SELECT DATE(v.visit_time) AS visit_date,  -- 将访问时间转为日期格式(去掉时分秒)v.user_id,                         -- 用户IDCASE -- 判断用户类型:注册后7天内访问的为新用户,否则为老用户WHEN DATEDIFF(v.visit_time, u.register_date) <= 7 THEN '新用户'ELSE '老用户'END AS user_type                   -- 用户类型标记FROM user_visits v                     -- 访问记录表JOIN users u ON v.user_id = u.user_id  -- 关联用户信息表
),-- 第二步:按日期和用户类型分组统计PV量
daily_pv AS (SELECT visit_date,       -- 访问日期user_type,        -- 用户类型COUNT(*) AS pv_count  -- 计算每日每类用户的PV总量FROM daily_user_types -- 使用上一步的结果GROUP BY visit_date, user_type  -- 按日期和用户类型分组
),-- 第三步:计算每日的总PV量(不分用户类型)
daily_totals AS (SELECT visit_date,              -- 访问日期SUM(pv_count) AS daily_total  -- 计算每日所有用户的总PV量FROM daily_pv                -- 使用上一步的分组统计结果GROUP BY visit_date          -- 按日期分组
)-- 最终查询:计算每日每类用户的PV占比
SELECT d.visit_date,                      -- 访问日期d.user_type,                       -- 用户类型d.pv_count,                        -- 该类型的PV数量ROUND(d.pv_count * 100.0 / t.daily_total, 2) AS percentage  -- 计算占比(百分比)
FROM daily_pv d                       -- 每日用户类型分组统计
JOIN daily_totals t ON d.visit_date = t.visit_date  -- 关联每日总PV量(按日期匹配)
ORDER BY d.visit_date, d.user_type;   -- 按日期和用户类型排序

3. 识别"高价值用户"(UV高且PV高)

用户访问日志表user_visits,包含字段:user_id(用户ID),visit_time(访问时间),page_url(访问页面)。

  • 找出访问天数多且访问页面多——前20%的"高价值用户"

使用 NTILE 分桶

在这里插入图片描述


留个作业:(有难度哈)

基于流量与转化率的酒店分类筛选

现有一张名为 hotel 的表,用于记录酒店的相关数据,表结构如下:

字段名数据类型说明
id唯一标识酒店的唯一编号
pv整数酒店的展现量(PV,Page View)
cnt整数酒店的支付订单量

要求根据上述表中的数据,筛选出以下三类酒店的 id

  1. 高流高转:在流量降序排列的前 20% 的酒店中,筛选出有支付订单(cnt > 0)的酒店,并且这些酒店的转化率在降序排列的前 20%。
  2. 高流低转:在流量降序排列的前 20% 的酒店中,筛选出转化率升序排列的前 20% 的酒店(包括没有支付订单的酒店,即 cnt = 0 的情况)。
  3. 低流高转:在流量升序排列的前 20% 的酒店中,筛选出有支付订单(cnt > 0)的酒店,并且这些酒店的转化率在降序排列的前 20%。

这道题有点优雅:

在这里插入图片描述


-- 使用 WITH 子句创建一个名为 hotel_stats 的公共表表达式(CTE)
with hotel_stats as (-- 从 hotel 表中选择所需的列,并计算一些统计信息select id,-- 计算酒店的总数,使用窗口函数对整个结果集进行计数count(*) over() as all_hotel_num,-- 对酒店按照展现量(pv)降序排名,使用窗口函数 row_number()row_number() over(order by pv desc) as rk_pv,   -- 展现量-- 判断酒店是否有支付订单,有则标记为 1,否则标记为 0case when cnt > 0 then 1 else 0 end as has_order,  -- 有订单-- 对酒店按照转化率(cnt / pv)降序排名,使用窗口函数 row_number()row_number() over(order by case when pv = 0 then 0 else cnt / pv end desc) as rk_change  -- 转化率from hotel
)
-- 从 hotel_stats 子查询中选择所需的列,并根据排名情况对酒店进行分类
select id,-- 根据排名和是否有订单的情况,对酒店进行分类case -- 高流高转:流量排名在前 20% 且有订单  且转化率排名在前 20%when rk_pv / all_hotel_num <= 0.2 and has_order = 1 and rk_change / all_hotel_num <= 0.2 then '高流高转'-- 高流低转:流量排名在前 20% 且转化率排名在后 20%when rk_pv / all_hotel_num <= 0.2 and rk_change / all_hotel_num >= 0.8 then '高流低转'-- 低流高转:流量排名在后 20% 且有订单且转化率排名在前 20%when rk_pv / all_hotel_num >= 0.8 and has_order = 1 and rk_change / all_hotel_num <= 0.2 then '低流高转'-- 其他情况标记为未知else '未知' end as lable
from hotel_stats;

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/74814.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】第八节—string类(上)——详解+代码示例

hello&#xff0c;又见面了&#xff01; 云边有个稻草人-CSDN博客 C_云边有个稻草人的博客-CSDN博客——C专栏&#xff08;质量分高达97&#xff01;&#xff09; 菜鸟进化中。。。 目录 一、为什么要学习string类&#xff1f; 1.1 C语言中的字符串 1.2 面试题(暂不做讲解) …

如何判断JVM中类和其他类是不是同一个类

如何判断JVM中的类是否为同一个类 在Java虚拟机(JVM)中&#xff0c;判断两个类是否相同需要同时满足以下三个条件&#xff1a; 1. 类全限定名必须相同 包括包名类名的完整路径必须完全一致例如&#xff1a;java.lang.String和com.example.String被视为不同类 2. 加载该类的…

ifconfig 使用详解

目录 一、基本语法二、常见用途及示例1. 查看所有网络接口信息2. 启用/禁用网络接口3. 配置 IP 地址和子网掩码4. 修改 MAC 地址5. 启用混杂模式&#xff08;Promiscuous Mode&#xff09;6. 设置 MTU&#xff08;最大传输单元&#xff09; 三、其他选项四、常见问题1. 新系统中…

1. 标准库的强依赖(核心原因)

1. 标准库的强依赖&#xff08;核心原因&#xff09; 容器操作&#xff08;如 std::vector 扩容&#xff09; 当标准库容器&#xff08;如 std::vector&#xff09;需要重新分配内存时&#xff0c;它会尝试移动现有元素到新内存&#xff0c;而非拷贝&#xff08;为了性能&…

【MySQL】常用SQL--持续更新ing

一、配置信息类 1.查看版本 select version; 或 select version(); 2.查看配置 show global variables where variable_name in (basedir,binlog_format,datadir,expire_logs_days,innodb_buffer_pool_size,innodb_log_buffer_size,innodb_log_file_size,innodb_log_files_i…

Day82 | 灵神 | 快慢指针 重排链表

Day82 | 灵神 | 快慢指针 重排链表 143.重排链表 143. 重排链表 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者直接给跪了&#xff0c;这个难度真是mid吗 直接去看灵神的视频 环形链表II【基础算法精讲 07】_哔哩哔哩_bilibili 1.简单来说就是&#xf…

常见的微信个人号二次开发功能

一、常见开发功能 1. 好友管理 好友列表维护 添加/删除好友 修改好友信息&#xff08;备注、标签等&#xff09; 分组管理 创建/编辑/删除标签 好友分类与筛选 2. 消息管理 信息发送 支持多类型内容&#xff1a;文本、图片、视频、文件、小程序、名片、URL链接等 附加功…

Android打包及上架应用市场问题处理

一、Gradle 配置参数含义&#xff1a; compileSdkVersion: 29 表示项目编译时使用的 Android SDK 版本为 API 29&#xff08;Android 10&#xff09;&#xff0c;仅影响编译阶段的行为&#xff08;如代码语法检查、资源处理等&#xff09;&#xff0c;不直接影响运行时兼容性。…

Docker 从入门到进阶 (Win 环境) + Docker 常用命令

目录 引言 一、准备工作 1.1 系统要求 1.2 启用虚拟化 二、安装Docker 2.1 安装WSL 2 2.2 安装Docker Desktop 2.3检查是否安装成功 三、配置Docker 3.1 打开Docker配置中心 四、下载和管理Docker镜像 4.1 拉取镜像 4.2 查看已下载的镜像 4.3 运行容器 4.4 查看正…

计算机视觉5——运动估计和光流估计

一、运动估计 &#xff08;一&#xff09;运动场&#xff08;Motion Field&#xff09; 定义与物理意义 运动场是三维场景中物体或相机运动在二维图像平面上的投影&#xff0c;表现为图像中每个像素点的运动速度矢量。其本质是场景点三维运动&#xff08;平移、旋转、缩放等&a…

介质访问控制——信道划分

什么是介质访问 介质访问&#xff08;Medium Access&#xff09;​ 是计算机网络中一种规则&#xff0c;用来解决 ​​“多台设备如何共享同一根网线/信道传输数据”​ 的问题。你可以理解为&#xff1a; 想象一条只能容一辆车通过的独木桥&#xff08;网络中的网线、Wi-Fi信道…

ERP系统五大生产模式概述

制造业中,选择合适的生产模式是企业高效运营的关键。 以下是ERP系统支持的五大核心生产模式及其特点总结: 1. MTS(按库存生产) - 定义:先生产后销售,基于需求预测提前备货。 - 适用场景:需求稳定、标准化程度高的产品(如日用品、家电)。 - 优点:交货快、生产…

ubantu操作笔记

安装ssh服务 1.1 基本安装 sudo apt update sudo apt install openssh-server -y sudo systemctl start ssh sudo systemctl enable ssh 1.2 配置远程root登陆 # 0. 设置root密码 sudo passwd root # 1. 安装vim依赖 sudo apt-get install vim -y # 2. 编辑配置文件 s…

2-vim编辑器的安装和使用

一.常用工具介绍 前言&#xff1a; 我们想要编写c语言代码&#xff0c;可以使用linux系统提供的工具才能进行代码的编辑。代码编写后&#xff0c;我们还需要验证代码的书写正确。这就需要借助编译器来进行验证。linux系统为我们提供了比较好的开发工具。 vim编辑器&#xff…

小刚说C语言刷题——第16讲 switch语句

在日常生活中&#xff0c;我们经常会遇到多分支的情况。当分支较多时&#xff0c;我们可以用嵌套的if-else语句。但是这样会让结构显得混乱。这个时候我们可以考虑用switch语句。 1.语法格式 switch (表达式) { case 常量表达式1&#xff1a; 语句1; break; case 常量表达式…

使用 Python 连接 PostgreSQL 数据库,从 `mimic - III` 数据库中筛选数据并导出特定的数据图表

要使用 Python 连接 PostgreSQL 数据库&#xff0c;从 mimic - III 数据库中筛选数据并导出特定的数据图表&#xff0c;你可以按照以下步骤操作&#xff1a; 安装所需的库&#xff1a;psycopg2 用于连接 PostgreSQL 数据库&#xff0c;pandas 用于数据处理&#xff0c;matplot…

过孔的载流能力

PCB过孔的载流能力&#xff08;即能安全承载的电流大小&#xff09;主要与以下因素相关&#xff1a; 1. 过孔的尺寸 孔径&#xff08;直径&#xff09;&#xff1a;孔径越大&#xff0c;横截面积越大&#xff0c;载流能力越强。 孔壁铜厚&#xff1a;电镀铜的厚度&#xff08…

(done) 并行计算 CS149 Lecture2 (现代多核处理器) (SIMD, 多核, 超标量, 数据预取, 超线程)

视频 url: https://www.bilibili.com/video/BV1du17YfE5G?spm_id_from333.788.videopod.sections&vd_source7a1a0bc74158c6993c7355c5490fc600&p2 大佬笔记 url: https://zhuanlan.zhihu.com/p/8129089606 先看视频&#xff1a; Lecture 0 ~ 28min 的内容基本就是 c…

Leetcode 3508. Implement Router

Leetcode 3508. Implement Router 1. 解题思路2. 代码实现 题目链接&#xff1a;3508. Implement Router 1. 解题思路 这一题就是按照题意写作一下对应的函数即可。 我们需要注意的是&#xff0c;这里&#xff0c;定义的类当中需要包含以下一些内容&#xff1a; 一个所有i…

Linux: 系统内核中的信号

目录 一 前言 二 信号在内核中的表示 三 sigset_t 四 信号集操作 1. sigpending() 2. sigemptyset() 3. sigfillset() 4. sigaddset ()和sigdelset() 5. sigismember() 6. sigprocmask() 五 深入理解信号的捕捉流程 一 前言 在Linux: 进程信号初识-CSDN博客信…