一、Linux + Shell 巩固
- 复习昨天的 grep / find / wc / du 四个大数据高频命令
- 写一个小脚本:统计当前目录下所有 .py 文件总行数
#!/bin/bash
total=0 # 添加总计变量
for file in *.py; do
if [ -f "$file" ]; then
lines=$(wc -l < "$file")
echo "文件: $file 行数: $lines"
total=$((total + lines)) # 累加行数
fi
done
echo "------------------------"
echo "总行数: $total"
二、SQL 高强度训练
- 第二高的薪水

去最大,取最大
select max(salary) as SecondHighestSalary
from employee
where salary < (select max(salary) from employee)
- 第 N 高的薪水

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
set n = n - 1;
RETURN (
select distinct salary
from employee
order by salary desc
limit n, 1
);
END
DISTINCT:去除重复的薪水
ORDER BY salary DESC:按薪水降序排列(最高在前)
LIMIT offset, count
: offset:跳过的记录数(即 n = n-1)
: count:取 1 条记录
- 分数排名
窗口函数用法
窗口函数() OVER (
PARTITION BY 分组字段 -- 可选,按什么分组
ORDER BY 排序字段 -- 必需,按什么排序
) AS 别名
-
rank()
跳号(1,2,2,4)并列占位,下一个跳号 -
dense_rank()
不跳号(1,2,2,3)并列不占位,连续排名 -
row_number()
唯一连续(1,2,3,4)不重复,即使分数相同也分先后


select score,
dense_rank() over (order by score desc) as 'rank'
from scores
RANK 是 MySQL 的保留关键字,不能直接作为列别名(除非加反引号)
- 连续出现的数字

语法
LAG() 访问当前行之前的行 向上(过去)
LEAD() 访问当前行之后的行 向下(未来)
LAG(column_name, offset, default_value) OVER (PARTITION BY ... ORDER BY ...)
LEAD(column_name, offset, default_value) OVER (PARTITION BY ... ORDER BY ...)
WITH consecutive_check AS (
SELECT
num,
LAG(num, 1) OVER (ORDER BY id) AS prev_num,
LAG(num, 2) OVER (ORDER BY id) AS prev_prev_num,
LEAD(num, 1) OVER (ORDER BY id) AS next_num,
LEAD(num, 2) OVER (ORDER BY id) AS next_next_num
FROM Logs
)
SELECT DISTINCT num AS ConsecutiveNums
FROM consecutive_check
WHERE (num = prev_num AND num = prev_prev_num) -- 当前与前两个相同
OR (num = prev_num AND num = next_num) -- 当前与前一个、后一个相同
OR (num = next_num AND num = next_next_num); -- 当前与后两个相同
三、PySpark 入门:第一个真正的程序
- 创建 SparkSession
- 读取一个本地 CSV(自己随便造 5 行数据)
- 用 Spark SQL 做一次查询:筛选、计数、分组
- 打印结果
from pyspark.sql import SparkSession
import pandas as pd
# 先创建测试CSV文件(5行数据)
test_data = pd.DataFrame({
'name': ['张三', '李四', '王五', '赵六', '小明'],
'age': [25, 18, 30, 22, 19],
'city': ['北京', '上海', '北京', '广州', '上海'],
'salary': [8000, 5000, 12000, 7000, 6000]
})
test_data.to_csv('test.csv', index=False, encoding='utf-8')
# 1. 创建SparkSession
spark = SparkSession.builder \
.appName("Day3_Test") \
.master("local[*]") \
.getOrCreate()
# 2. 读取CSV
df = spark.read.csv("test.csv", header=True, inferSchema=True)
# 3. 查看数据
print("原始数据:")
df.show()
df.printSchema()
# 4. 使用Spark SQL进行查询
# 方式1:使用DataFrame API
print("\n方式1 - DataFrame API:筛选年龄>20,按城市分组计数:")
result1 = df.filter("age > 20").groupBy("city").count()
result1.show()
# 方式2:注册临时视图,使用纯SQL
df.createOrReplaceTempView("people")
print("\n方式2 - 纯SQL语法:筛选年龄>20,按城市分组计数:")
result2 = spark.sql("""
SELECT city, COUNT(*) as count
FROM people
WHERE age > 20
GROUP BY city
ORDER BY count DESC
""")
result2.show()
# 额外示例:查询平均薪资
print("\n额外查询:各城市平均薪资(年龄>20):")
result3 = spark.sql("""
SELECT city, AVG(salary) as avg_salary
FROM people
WHERE age > 20
GROUP BY city
""")
result3.show()
# 停止SparkSession
spark.stop()

- SparkSession 是什么?
在 PySpark 中,SparkSession 是一个统一的入口点,用于与 Spark 进行交互。它是 Spark 2.0 引入的新特性,替代了旧版中的 SparkContext、SQLContext 和 HiveContext 等。SparkSession 为用户提供了一个单一的接口,方便使用 Spark 的各种功能,包括 DataFrame、SQL、Streaming 等。
从代码示例可以看出,创建 SparkSession 对象的方式通常如下:
from pyspark.sql import SparkSession
spark = SparkSession.builder \
.appName("Python Spark SQL basic example") \
.config("spark.some.config.option", "some-value") \
.getOrCreate()
在上述代码中,SparkSession.builder 用于构建 SparkSession 对象,appName 方法用于设置应用程序的名称,config 方法用于设置 Spark 的配置选项,getOrCreate 方法用于获取已存在的 SparkSession 对象,如果不存在则创建一个新的对象。
此外,在使用 SparkSession 时,可以利用它读取文件,如读取 CSV 文件:
df_csv = ss.read.csv(path='/test/stu.csv', sep=',', inferSchema=True, schema='name string,age int,gender string,phone string,email string,city string,address string')
这里的 ss 是 SparkSession 对象,通过 read.csv 方法读取 CSV 文件并创建 DataFrame。
- DataFrame 是什么?

在 PySpark 中,DataFrame 是组织成命名列(named columns)的分布式数据集合。它在概念上等同于关系数据库中的表或 R/Python 中的数据框,但在幕后做了更丰富的优化。DataFrames 可以从多种来源构建,例如结构化数据文件、Hive 中的表、外部数据库或现有 RDD。
以下是一个简单的示例,展示如何使用 SparkSession 读取 CSV 文件并创建 DataFrame:
from pyspark.sql import SparkSession
# 创建 SparkSession
spark = SparkSession.builder \
.appName("Python Spark SQL basic example") \
.getOrCreate()
# 读取 CSV 文件
fileDF = spark.read.csv('hdfs://tmp/ratings.csv', sep = ',', header = True)
# 显示 DataFrame 内容
fileDF.show()
# 获取前 2 行
print(fileDF.head(2))
-
Spark SQL 和普通 SQL 几乎一样

- 相同点:在标准 SQL 语法的基础功能上,Spark SQL 和普通 SQL 是一致的,都支持基础的 CRUD(创建、读取、更新、删除)和聚合操作等
- 不同点主要体现在以下几个方面:
- 设计定位:普通 SQL 是传统关系型数据库的标准查询语言,用于 OLTP(事务处理)和简单 OLAP(分析处理),语法标准化但功能受限,缺乏分布式计算能力;而 Spark SQL 是基于 Spark 引擎的分布式 SQL 实现,扩展了标准 SQL 语法,支持批处理和微批流处理,强调与 Spark 生态(如 MLlib、GraphX)的集成。
- 处理模型:普通 SQL 采用单机/主从架构,执行模式下延迟为毫秒级(OLTP 场景),仅处理时间;Spark SQL 采用分布式微批(流)或批处理,延迟为秒级(微批),以处理时间为主。
- 语法与功能扩展:普通 SQL 的窗口函数(如 OVER 子句)需特定数据库支持(如 Oracle、PostgreSQL);Spark SQL 扩展了 UDF(用户定义函数)、UDAF(用户定义聚合函数)、窗口函数(如 TUMBLE),还支持 DataFrame API 和 Catalyst 优化器。
示例代码
以下是一个简单的普通 SQL 查询示例和对应的 Spark SQL 查询示例:
-- 普通 SQL 查询示例(假设使用 MySQL)
SELECT COUNT(*) FROM users WHERE age > 18;
# Spark SQL 查询示例
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName("SparkSQLExample").getOrCreate()
data = [("Alice", 25), ("Bob", 20), ("Charlie", 17)]
columns = ["name", "age"]
df = spark.createDataFrame(data, columns)
df.createOrReplaceTempView("users")
result = spark.sql("SELECT COUNT(*) FROM users WHERE age > 18")
result.show()
四、算法题
- 合并两个有序链表
# Definition for singly-linked list.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def mergeTwoLists(self, l1, l2):
# 创建虚拟头节点
dummy = ListNode(0)
current = dummy
# 遍历两个链表
while l1 and l2:
if l1.val <= l2.val:
current.next = l1
l1 = l1.next
else:
current.next = l2
l2 = l2.next
current = current.next
# 连接剩余部分
if l1:
current.next = l1
if l2:
current.next = l2
return dummy.next
1118

被折叠的 条评论
为什么被折叠?



