大数据开发学习Day3

一、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 高强度训练

  1. 第二高的薪水
    在这里插入图片描述
    去最大,取最大
select max(salary) as SecondHighestSalary
from employee
where salary < (select max(salary) from employee)
  1. 第 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 条记录

  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 的保留关键字,不能直接作为列别名(除非加反引号)

  1. 连续出现的数字
    在这里插入图片描述
    语法
    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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值