Filtre linhas e trate valores ausentes

Big DataBeginner
Pratique Agora

Introdução

A empresa varejista agora consegue mapear arquivos para tabelas, mas uma tabela legível não está automaticamente pronta para relatórios. Alguns valores de status têm espaços extras, um identificador de cliente está ausente, outro é texto vazio, um preço é desconhecido e uma quantidade é zero. Uma consulta que ignore essas diferenças pode selecionar as linhas erradas ou exibir valores enganosos.

Você criará uma pequena fila de revisão: linhas pagas com quantidade positiva e preços conhecidos, texto de status normalizado e um valor padrão visível para um identificador de cliente ausente. Preços ausentes serão excluídos, não substituídos por zero. Exibir um rótulo de cliente desconhecido não cria um registro real de cliente nem altera os dados de origem.

Este laboratório usa uma amostra separada de qualidade de dados com sete linhas, não os dados limpos de vendas dos laboratórios anteriores. Você primeiro combinará condições, depois examinará valores ausentes e funções simples, adicionará rótulos com CASE e mudará uma condição para conferir sua compreensão. Você já conhece SELECT, WHERE, ORDER BY e arquivos SQL. Todos os serviços e dados de tabela são preparados de forma independente; use o Terminal.

Combine condições de linha de forma consciente

Nesta etapa, você combinará um teste de quantidade com alternativas de status e entenderá por que os parênteses importam.

Comece no projeto:

cd /home/labex/project

Leia o CSV preparado antes de consultar:

cat /home/labex/project/data/quality-orders.csv

Há sete linhas de negócio após o cabeçalho. Observe os espaços ao redor de paid em r1, os marcadores \N em r2 e r3, o campo vazio de cliente em r6 e a quantidade zero em r7. A tabela preparada interpreta \N como SQL NULL; um campo de texto vazio continua sendo uma string vazia. Você examinará essas distinções em breve.

Comparações SQL como quantity > 0 testam cada linha. AND exige que ambas as condições sejam verdadeiras; OR aceita qualquer uma das alternativas. Os parênteses agrupam as alternativas de status para que uma linha pendente com quantidade zero não contorne o teste de quantidade.

Salve um primeiro filtro usando o padrão de arquivo SQL que você já praticou:

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

Execute o arquivo com a conexão conhecida do Beeline e as opções de saída separada por tabulação:

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

Leia o resultado:

cat /home/labex/project/output/conditions.txt

As linhas de pedidos deverão ser:

r2 1 paid
r3 1 paid
r4 1 pending
r6 1 paid

r7 é excluído por sua quantidade, embora seu status seja pending. r1 é excluído porque seu texto armazenado contém espaços e não é exatamente 'paid'. O preço ausente em r3 ainda não foi tratado por este filtro. Cada condição resolve um problema específico; as próximas etapas acrescentam as partes que faltam.

Diferencie valores ausentes de texto vazio

Nesta etapa, você testará NULL corretamente e normalizará valores de exibição sem alterar as linhas armazenadas.

NULL representa um valor ausente ou desconhecido. Ele não é o texto 'NULL' e não é uma string vazia. Use IS NULL ou IS NOT NULL para testá-lo, em vez de = NULL.

Solicite identificadores de cliente ausentes e vazios separadamente. A primeira instrução seleciona r2; a segunda seleciona 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 = '';"

Duas pequenas funções ajudam a exibir esses registros com clareza. TRIM(text) remove espaços das extremidades de uma string. COALESCE(a,b) retorna o primeiro valor diferente de NULL, portanto pode exibir 'unknown' quando o identificador é NULL. Ela não substitui texto vazio nem modifica a tabela subjacente.

Salve uma consulta de inspeção que aplique essas funções às sete linhas:

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

Execute-a:

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

Leia o registro:

cat /home/labex/project/output/normalized-values.txt

Encontre três observações: r1 agora exibe paid sem espaços extras, r2 exibe o rótulo de cliente unknown e r6 ainda tem um campo de cliente vazio. r3 tem preço NULL. Um valor padrão de exibição é adequado para o rótulo de cliente ausente nesta fila de revisão, mas inventar um preço zero representaria o pedido de forma incorreta. O filtro final excluirá os preços desconhecidos.

Rotule e selecione uma fila de revisão

Nesta etapa, você adicionará um rótulo legível de status de pagamento e combinará as verificações de qualidade de linha em uma consulta.

Uma expressão SQL CASE escolhe um valor a partir de condições. Ela avalia os ramos WHEN em ordem, usa o valor THEN correspondente e recorre a ELSE quando nenhum ramo corresponde. Você rotulará linhas pagas como Payment received, linhas pendentes como Awaiting payment e outros status como Other status.

Visualize os rótulos em todas as linhas antes de adicionar o filtro da fila de revisão:

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;"

Localize r5, cujo status refunded usa o ramo ELSE. r4 e r7 são rotulados como aguardando pagamento. Um rótulo de status descreve o status; sozinho, ele não valida quantidade nem preço.

Agora monte a regra completa da fila: quantidade positiva, preço conhecido e status pago normalizado. O identificador de cliente de origem permanece inalterado. No resultado da consulta, exiba um rótulo de cliente com COALESCE. O resultado exibido não inclui uma cópia separada do identificador original. Salve a consulta:

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

Execute-a de forma independente:

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

Leia o resultado:

cat /home/labex/project/output/filtered-orders.txt

Linhas de pedidos esperadas:

r1 c1 paid Payment received
r2 unknown paid Payment received
r6  paid Payment received

O campo vazio de exibição do cliente em r6 é intencional: ele é texto vazio, não NULL. r1 é incluído após a remoção dos espaços do status. r3 é excluído porque seu preço é desconhecido, enquanto linhas pendentes, reembolsadas e com quantidade zero ficam fora desta fila. Você definiu as linhas pretendidas sem fingir que preços ausentes são zero.

Mude uma condição e preveja o resultado

Nesta etapa, você reutilizará as mesmas expressões de exibição e regras de qualidade para uma fila de pedidos pendentes.

Antes de executar qualquer coisa, preveja o resultado se apenas a condição final de status mudar para pending. r4 tem quantidade positiva e preço conhecido, enquanto r7 tem quantidade zero. Apenas r4 deverá permanecer, e seu rótulo CASE deverá ser Awaiting payment.

Mantenha a primeira consulta intacta e salve um segundo arquivo. Suas expressões selecionadas e verificações de qualidade não mudam; apenas o valor final de status em WHERE é diferente:

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

Execute-a:

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

Leia a saída:

cat /home/labex/project/output/pending-review.txt

Linha de pedido esperada:

r4 c1 pending Awaiting payment

A tabela não mudou; a consulta selecionou outro conjunto de linhas e a expressão CASE existente escolheu o rótulo correspondente. No próximo laboratório, você criará totais a partir de linhas selecionadas corretamente, em vez de combinar regras de qualidade de dados e uma primeira experiência com agregação em um único salto.

Resumo

Você combinou condições com AND, OR e parênteses, distinguiu NULL de texto vazio e usou TRIM e COALESCE para um comportamento explícito de exibição. Adicionou rótulos CASE e definiu uma fila de revisão sem inventar valores monetários nem alterar os dados de origem.

A mudança de uma condição produziu a fila de pendentes prevista, preservando as verificações de qualidade. A seguir, você agregará linhas de pedidos limpas e selecionadas conscientemente em medidas de vendas.