介绍
零售商现在能将文件映射为表,但表可读不代表已经适合报表。有些状态值带多余空格,一个客户标识符缺失,另一个是空文本,一个价格未知,还有一个数量为零。忽略这些区别的查询可能选错行,或显示误导性的值。
你将构建一个小型审核队列:数量为正、价格已知的已付款行,状态文本经过规范化,并为缺失客户标识符显示明确默认值。缺失价格会被排除,不会替换为零。显示未知客户标签,不会创建真实客户记录,也不会改变源数据。
本实验使用独立的七行数据质量样本,不使用之前实验中的干净销售数据。你将先组合条件,再检查缺失值和简单函数,用 CASE 添加标签,最后改变一个条件检验理解。你已了解 SELECT、WHERE、ORDER BY 和 SQL 文件。所有服务和表数据均独立准备;请使用终端。
有意识地组合行条件
在这一步中,你将把数量检查与多个状态选项组合起来,并理解括号为什么重要。
进入项目目录:
cd /home/labex/project
查询之前先读取预置 CSV:
cat /home/labex/project/data/quality-orders.csv
表头之后有七条业务行。注意 r1 中 paid 两侧的空格、r2 和 r3 中的 \N 标记、r6 中的空客户字段,以及 r7 中的零数量。预置表将 \N 解释为 SQL NULL;空文本字段仍是空字符串。稍后会检查这些区别。
SQL 比较条件(例如 quantity > 0)会检查每一行。AND 要求两个条件都为真;OR 接受任一选项。括号将状态选项分组,防止数量为零的待付款行绕过数量检查。
使用已练习过的 SQL 文件方式保存首次筛选:
cat > /home/labex/project/queries/conditions.sql <<'SQL'
USE retail_filters;
SELECT order_id, quantity, order_status
FROM quality_orders
WHERE quantity > 0
AND (order_status = 'paid' OR order_status = 'pending')
ORDER BY order_id;
SQL
使用熟悉的 Beeline 连接和制表符分隔输出选项运行文件:
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -f /home/labex/project/queries/conditions.sql > /home/labex/project/output/conditions.txt
读取结果:
cat /home/labex/project/output/conditions.txt
订单行应该为:
r2 1 paid
r3 1 paid
r4 1 pending
r6 1 paid
r7 虽然状态是待付款,但因数量而被排除。r1 被排除,是因为存储文本包含空格,不完全等于 'paid'。这个筛选还没有处理 r3 缺失价格的问题。每个条件解决一个具体问题;接下来的步骤会补齐缺少的部分。
区分缺失值和空文本
在这一步中,你将正确检查 NULL,并规范显示值,而不改变存储行。
NULL 表示缺失或未知值。它不是文本 'NULL',也不是空字符串。请使用 IS NULL 或 IS NOT NULL 检查,不要使用 = NULL。
分别查询缺失和空的客户标识符。第一条语句选择 r2,第二条选择 r6:
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e "SELECT order_id FROM retail_filters.quality_orders WHERE customer_id IS NULL; SELECT order_id FROM retail_filters.quality_orders WHERE customer_id = '';"
两个小函数可以让显示更清楚。TRIM(text) 移除字符串两端的空格。COALESCE(a,b) 返回第一个非 NULL 值,因此可在标识符为 NULL 时显示 'unknown'(未知)。它不替换空文本,也不修改底层表。
保存一个对全部七行应用这些函数的查看查询:
cat > /home/labex/project/queries/normalized-values.sql <<'SQL'
USE retail_filters;
SELECT order_id,
COALESCE(customer_id, 'unknown') AS customer_label,
TRIM(order_status) AS clean_status,
unit_price
FROM quality_orders
ORDER BY order_id;
SQL
运行它:
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -f /home/labex/project/queries/normalized-values.sql > /home/labex/project/output/normalized-values.txt
读取记录:
cat /home/labex/project/output/normalized-values.txt
找到三个观察点:r1 现在显示不带填充空格的 paid,r2 显示客户标签 unknown,r6 的客户字段仍为空。r3 的价格为 NULL。对于这个审核队列,给缺失客户标签设置显示默认值是合适的,但虚构零价格会歪曲订单。最终筛选将排除未知价格。
添加标签并选择审核队列
在这一步中,你将添加易读的付款状态标签,并把行质量检查合并到一个查询中。
SQL CASE 表达式根据条件选择一个值。它按顺序判断 WHEN 分支,使用匹配的 THEN 值,没有分支匹配时使用 ELSE。你将把已付款行标为 Payment received(已收到付款),待付款行标为 Awaiting payment(等待付款),其他状态标为 Other status(其他状态)。
添加审核队列筛选之前,先预览全部行的标签:
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e "SELECT order_id, CASE WHEN TRIM(order_status) = 'paid' THEN 'Payment received' WHEN TRIM(order_status) = 'pending' THEN 'Awaiting payment' ELSE 'Other status' END AS payment_label FROM retail_filters.quality_orders ORDER BY order_id;"
找到 r5,它的退款状态进入 ELSE 分支。r4 和 r7 被标为等待付款。状态标签只描述状态,本身不会验证数量或价格。
现在建立队列的完整规则:数量为正、价格已知、规范化状态为已付款。源客户标识符保持不变。在查询结果中,用 COALESCE 显示客户标签。显示结果不包含另一个原始标识符副本。保存查询:
cat > /home/labex/project/queries/filtered-orders.sql <<'SQL'
USE retail_filters;
SELECT order_id,
COALESCE(customer_id, 'unknown') AS customer_label,
TRIM(order_status) AS clean_status,
CASE
WHEN TRIM(order_status) = 'paid' THEN 'Payment received'
WHEN TRIM(order_status) = 'pending' THEN 'Awaiting payment'
ELSE 'Other status'
END AS payment_label
FROM quality_orders
WHERE quantity > 0
AND unit_price IS NOT NULL
AND TRIM(order_status) = 'paid'
ORDER BY order_id;
SQL
独立执行它:
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -f /home/labex/project/queries/filtered-orders.sql > /home/labex/project/output/filtered-orders.txt
读取结果:
cat /home/labex/project/output/filtered-orders.txt
预期订单行如下:
r1 c1 paid Payment received
r2 unknown paid Payment received
r6 paid Payment received
r6 的客户显示字段留空是有意的:它是空文本而不是 NULL。r1 的状态去掉两端空格后被包含。r3 因价格未知而排除,待付款、已退款和零数量的行也不在此队列中。你明确了目标行,没有把缺失价格假装成零。
改变一个条件并预测结果
在这一步中,你将对待付款订单队列重用相同显示表达式和质量规则。
运行前先预测:如果只将最后的状态条件改为 pending,结果是什么?r4 的数量为正且价格已知,r7 的数量为零。应该只剩 r4,其 CASE 标签应为 Awaiting payment。
保持第一个查询完整,并保存第二个文件。所选表达式和质量检查都不变,只有最后的 WHERE 状态值不同:
cat > /home/labex/project/queries/pending-review.sql <<'SQL'
USE retail_filters;
SELECT order_id,
COALESCE(customer_id, 'unknown') AS customer_label,
TRIM(order_status) AS clean_status,
CASE
WHEN TRIM(order_status) = 'paid' THEN 'Payment received'
WHEN TRIM(order_status) = 'pending' THEN 'Awaiting payment'
ELSE 'Other status'
END AS payment_label
FROM quality_orders
WHERE quantity > 0
AND unit_price IS NOT NULL
AND TRIM(order_status) = 'pending'
ORDER BY order_id;
SQL
运行它:
beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -f /home/labex/project/queries/pending-review.sql > /home/labex/project/output/pending-review.txt
读取输出:
cat /home/labex/project/output/pending-review.txt
预期订单行如下:
r4 c1 pending Awaiting payment
表没有改变;查询选择了另一组行,现有 CASE 表达式选出了对应标签。下个实验中,你将在正确选出的行上建立总计,不会一下子同时引入数据质量规则和首次聚合。
总结
你使用 AND、OR 和括号组合条件,区分 NULL 与空文本,并用 TRIM 和 COALESCE 明确控制显示行为。你添加了 CASE 标签,定义了审核队列,没有虚构金额或改变源数据。
只修改一个条件,就在保留质量检查的同时生成了预测中的待付款队列。接下来,你将对干净且有意选择的订单行进行聚合,形成销售指标。



