21st Jul 2022 12 minutos de leitura Top 5 Perguntas de Entrevista SQL CTE Tihomir Babic sql cte empregos e carreira Índice Tabela para as perguntas 1, 2, e 3 Pergunta da Entrevista 1: Encontre o Salário Médio por Departamento Consulta de soluções Explicação da consulta da solução A Tabela de Resultados A explicação do resultado Você pode interpretar as linhas restantes no resultado da mesma forma. Entrevista Pergunta 2: Encontre o salário mais alto por departamento Consulta de soluções Explicação da consulta da solução A Tabela de Resultados O Resultado Explicação Entrevista Pergunta 3: Encontre todos os funcionários sob um gerente específico Consulta de soluções Explicação da consulta da solução A Tabela de Resultados O Resultado Explicação Tabelas utilizadas para as perguntas 4 e 5 Entrevista Questão 4: Encontre o número médio de pedidos Consulta de soluções Explicação da consulta da solução A tabela de resultados O Resultado Explicação Entrevista Pergunta 5: Encontre o número de dias consecutivos com o pedido Consulta de soluções Explicação da consulta da solução A tabela de resultados O Resultado Explicação Quando os CTEs são úteis? Quer saber mais sobre as Expressões da Tabela Comum SQL? Aqui estão cinco perguntas (e soluções!) sobre CTEs que você (provavelmente) será perguntado em uma entrevista. Não estou dizendo que você receberá estas perguntas do CTE SQL em cada entrevista de emprego. Mas quando você as fizer, elas provavelmente estarão na linha das cinco que estou prestes a mostrar aqui. Além das perguntas teóricas sobre CTEs, não há muitas variações nos cenários de CTE avaliados pelos entrevistadores. Analise estes cinco exemplos, e você terá uma boa base para realizar sua entrevista! Para isso, você tem que saber o que são expressões comuns de tabela SQL e como funciona sua sintaxe. Pronto para dar uma olhada nas perguntas? Vamos lá! Tabela para as perguntas 1, 2, e 3 Para o primeiro conjunto de perguntas, usaremos a tabela employees. Aqui está o que parece: idfirst_namelast_namedepartmentsalarymanager_id 1AngelikaVoulesMarketing5,293.742 2RozelleSwynleyMarketing8,295.0818 3WarrenWilleyEngineering9,126.7219 4LynelleWhitenManagement Board10,716.15NULL 5ConsolataRomanLegal8,456.064 6HoebartBaldockResearch and Development4,817.3420 7StarleneWatkissAccounting6,541.484 8BardeRibbensMarketing4,852.872 9LornePhilipsenEngineering7,235.593 10PedroNaldrettResearch and Development5,471.6220 11BrinaDillingerMarketing6,512.172 12VerileSonleyResearch and Development4,574.4120 13NobleGeerlingResearch and Development8,391.1820 14GareyMacAdamAccounting3,829.887 15TheoSorrellEngineering6,441.673 16ErminieGellingResearch and Development8,590.7020 17LoralieKoopAccounting5,248.467 18CalAndreyManagement Board11,258.82NULL 19QuinceyGamellManagement Board11,366.52NULL 20JanithMcGiffieResearch and Development7,428.8319 O que os dados lhe dizem? A primeira linha, por exemplo, diz que Angelika Voules trabalha em Marketing, e seu salário é de 5.293,74. Seu chefe tem uma identificação de gerente de 2; procure na coluna id, e você vê que o chefe de Angelika Voules é Rozelle Swynley. Há três filas com valores NULL na coluna manager_id: idfirst_namelast_namedepartmentsalarymanager_id 4LynelleWhitenManagement Board10,716.15NULL 18CalAndreyManagement Board11,258.82NULL 19QuinceyGamellManagement Board11,366.52NULL Significa que estes três employees não têm gerentes. Isto faz sentido, uma vez que todos os três estão no conselho de administração. Agora, vamos ver as perguntas da entrevista. Pergunta da Entrevista 1: Encontre o Salário Médio por Departamento Usando a tabela de funcionários, mostrar todos os funcionários, seus departamentos, salários e o salário médio em seu respectivo departamento. Encomende o resultado por departamento. Consulta de soluções WITH avg_salary AS ( SELECT AVG(salary) AS average_salary, department FROM employees GROUP BY department) SELECT e.first_name, e.last_name, e.department, e.salary, avgs.average_salary FROM employees e JOIN avg_salary avgs ON e.department = avgs.department ORDER BY department; Explicação da consulta da solução Esta consulta usa um CTE chamado avg_salary para calcular o salário médio por departamento. A declaração SELECT no CTE agrupa as linhas por departamento e usa a função agregada AVG() para calcular a média de cada departamento. Uma vez que temos isso, combinamos isso com outras colunas da tabela employees para completar a resposta à pergunta da entrevista. Para isso, nos juntamos à mesa employees com o CTE, como faríamos com duas mesas quaisquer. Selecionamos as colunas first_name, last_name, department, e salary da tabela employees, e a coluna average_salary do CTE. Por conveniência, usamos pseudônimos para a tabela e para o CTE. Finalmente, encomendamos o resultado por departamento. A Tabela de Resultados Eis como é o resultado: first_namelast_namedepartmentsalaryaverage_salary GareyMacAdamAccounting3,829.885,206.61 LoralieKoopAccounting5,248.465,206.61 StarleneWatkissAccounting6,541.485,206.61 WarrenWilleyEngineering9,126.727,601.33 LornePhilipsenEngineering7,235.597,601.33 TheoSorrellEngineering6,441.677,601.33 ConsolataRomanLegal8,456.068,456.06 CalAndreyManagement Board11,258.8211,113.83 QuinceyGamellManagement Board11,366.5211,113.83 LynelleWhitenManagement Board10,716.1511,113.83 AngelikaVoulesMarketing5,293.746,238.47 RozelleSwynleyMarketing8,295.086,238.47 BardeRibbensMarketing4,852.876,238.47 BrinaDillingerMarketing6,512.176,238.47 NobleGeerlingResearch and Development8,391.186,545.68 ErminieGellingResearch and Development8,590.706,545.68 VerileSonleyResearch and Development4,574.416,545.68 PedroNaldrettResearch and Development5,471.626,545.68 HoebartBaldockResearch and Development4,817.346,545.68 JanithMcGiffieResearch and Development7,428.836,545.68 A explicação do resultado Esta tabela nos diz que, por exemplo, o salário de Starlene Watkiss é de 6.541,48, e o salário médio em seu departamento (Contabilidade) é de 5.206,61. first_namelast_namedepartmentsalaryaverage_salary StarleneWatkissAccounting6,541.485,206.61 Você pode interpretar as linhas restantes no resultado da mesma forma. Entrevista Pergunta 2: Encontre o salário mais alto por departamento Encontre o funcionário com o salário mais alto em cada departamento. Mostrar seu primeiro e último nome, salários e departamentos. Consulta de soluções WITH highest_salary AS ( SELECT first_name, last_name, department, salary, RANK () OVER (PARTITION BY department ORDER BY salary DESC) AS salary_rank FROM employees) SELECT first_name, last_name, salary, department FROM highest_salary WHERE salary_rank = 1; Explicação da consulta da solução Desta vez, o CTE é nomeado highest_salary. Utilizamo-lo para classificar os funcionários dentro de cada departamento por salário. Como? Usando a função de janela RANK(). Dividimos os dados pelo departamento de colunas. Isto significa que classificamos os salários somente dentro de cada departamento, não em toda a empresa. Os dados são classificados de acordo com o salário da coluna em ordem decrescente porque queremos que o mais alto salary do departamento tenha a classificação de 1. Também selecionamos várias colunas da tabela employees no mesmo CTE. Precisamos dos dados deste CTE na próxima declaração SELECT. E, nessa declaração SELECT, selecionamos as colunas necessárias para responder à pergunta da entrevista. Todas as colunas são do CTE. Filtramos o resultado usando uma cláusula WHERE para obter apenas as linhas onde o nível salarial é 1, ou seja, as linhas com o salário mais alto. A Tabela de Resultados first_namelast_namesalarydepartment StarleneWatkiss6,541.48Accounting WarrenWilley9,126.72Engineering ConsolataRoman8,456.06Legal QuinceyGamell11,366.52Management Board RozelleSwynley8,295.08Marketing ErminieGelling8,590.70Research and Development O Resultado Explicação Não é muito difícil interpretar o resultado. Tomemos este funcionário como exemplo: first_namelast_namesalarydepartment ConsolataRoman8,456.06Legal Os dados mostrados nos dizem que a Consolata Roman tem o salário mais alto do Departamento Jurídico em 8.456,06. Passemos à terceira pergunta da entrevista SQL CTE. Entrevista Pergunta 3: Encontre todos os funcionários sob um gerente específico Encontre todos os funcionários que trabalham direta ou indiretamente sob o funcionário cujo ID é 18. Consulta de soluções WITH RECURSIVE subordinates AS ( SELECT id, first_name, last_name, manager_id FROM employees WHERE id = 18 UNION SELECT e.id, e.first_name, e.last_name, e.manager_id FROM employees e JOIN subordinates s ON e.manager_id = s.id ) SELECT * FROM subordinates WHERE id != 18; Explicação da consulta da solução Neste exemplo, não se trata apenas de um CTE regular - ao contrário, usamos um CTE recorrente para obter o resultado. A diferença na sintaxe é WITH RECURSIVE, em vez de apenas COM. O CTE é nomeado subordinatese depois vem a declaração SELECT tal como nos CTEs não-recursivos. Esta declaração seleciona certas colunas da tabela employees mas somente para o funcionário cuja identificação é 18. Então, usamos o operador UNION para vincular o resultado desta declaração SELECT com o resultado de outra declaração SELECT. Para isso, ambas as declarações SELECT precisam ter as mesmas colunas. A segunda declaração SELECT no CTE seleciona colunas onde manager_id (da tabela employees) é igual ao id (do CTE). Obtemos todos os dados para o funcionário cuja identificação é 18. Em seguida, encontramos os subordinados diretos, e por recorrência, encontramos os subordinados dos subordinados, até descermos toda a hierarquia da organização. Em seguida, obtemos as colunas dos subordinados do CTE e retiramos o funcionário cujo ID é 18. É isso aí! A Tabela de Resultados idfirst_namelast_namemanager_id 2RozelleSwynley18 1AngelikaVoules2 8BardeRibbens2 11BrinaDillinger2 O Resultado Explicação O chefe direto de Rozelle Swynley é o funcionário cujo gerente tem 18 anos de identificação. Mas Rozelle tem subordinados, também. Eles são Angelika Voules, Barde Ribbens, e Brina Dillinger. Sabemos disso porque a tabela mostra que a identificação do gerente deles é 2, que é a identificação de Rozelle Swynley. Eles são os subordinados diretos de Rozelle Swynley; eles também são subordinados indiretos do funcionário cujo ID é 18. O funcionário cujo ID é 18 é Cal Andrey, que não é mostrado no resultado porque o filtramos na cláusula WHERE. Tabelas utilizadas para as perguntas 4 e 5 Para as duas últimas perguntas da entrevista, utilizaremos as tabelas customers e orders. A tabela customers parece ser assim: idfirst_namelast_name 1SimonPaulson 2DylanBobson 3RebMackennack O orders mesa é um pouco maior: idorder_dateorder_amountcustomer_id 12021-10-0142.123 22021-10-01415.631 32021-10-0284.992 42021-10-0228.963 52021-10-0254.311 62021-10-0374.261 72021-10-0377.772 82021-10-0355.703 92021-10-0416.943 102021-10-0451.441 112021-10-0541.583 122021-10-0695.001 Esta segunda tabela contém dados sobre os pedidos feitos. A coluna customer_id é uma chave estrangeira para a chave primária da primeira tabela, para que possamos identificar qual cliente fez qual pedido. Tomemos a primeira linha como exemplo: idorder_dateorder_amountcustomer_id 12021-10-0142.123 É um pedido feito em 1 de outubro de 2021. O valor da mercadoria encomendada é 42,12, e o pedido foi feito pelo cliente cuja identificação é 3. Da tabela customersVejam, é Reb Mackennack. Vejamos as tarefas a serem resolvidas usando estas tabelas. Entrevista Questão 4: Encontre o número médio de pedidos Esta pergunta de entrevista pede que você use uma expressão de tabela comum SQL para encontrar o número médio de pedidos por cliente. Consulta de soluções WITH orders_count AS ( SELECT customer_id, COUNT(*) AS no_of_orders FROM orders GROUP BY customer_id) SELECT AVG(no_of_orders) AS avg_no_of_orders FROM orders_count; Explicação da consulta da solução Para obter o resultado, primeiro você conta o número de pedidos por cliente. Fazemos isto usando o CTE orders_count e a função COUNT() nela contida. Esta função conta o número de filas na tabela orders. Como não estamos interessados na contagem total de pedidos, mas sim no número de pedidos por cliente, eu agrupo o resultado pela coluna customer_id. Agora que temos o número de pedidos, é fácil calcular o número médio. Basta usar a função AVG() na declaração SELECT, e você terá a resposta para a pergunta da entrevista. A tabela de resultados avg_no_of_orders 4 O Resultado Explicação Uma mesa muito pequena requer uma explicação muito breve. A tabela acima mostra simplesmente que o número médio de pedidos por cliente é de quatro. Entrevista Pergunta 5: Encontre o número de dias consecutivos com o pedido Neste exemplo do CTE, é preciso calcular quantos dias seguidos cada cliente faz um pedido. Basicamente, é preciso calcular a duração de uma série contígua sem lacunas. Observe que todos os pedidos são feitos dentro do mesmo mês. Consulta de soluções WITH groupings_by_date AS ( SELECT c.id, c.first_name, c.last_name, RANK() OVER (PARTITION BY c.id ORDER BY o.order_date) AS row_number, o.order_date, EXTRACT(DAY FROM o.order_date) - RANK() OVER (PARTITION BY c.id ORDER BY o.order_date) AS date_group FROM customers c JOIN orders o ON c.id = o.customer_id ) SELECT id, first_name, last_name, COUNT(*) AS orders_in_row FROM groupings_by_date GROUP BY id, first_name, last_name, date_group; Explicação da consulta da solução Esta consulta bastante demorada começa com um CTE. Ela seleciona certas colunas das tabelas customers e orders. Há uma função de janela RANK(), como na pergunta 2. Desta vez, usamos esta função para alocar um número de linha para cada pedido dentro do mesmo cliente. Por esse motivo, dividimos os dados pela coluna id. A classificação é feita de acordo com a data da ordem (queremos que a classificação seja seqüencial). A outra função utilizada aqui é EXTRACT(). Sua finalidade é extrair a parte do dia da data do pedido para que possamos deduzir o número da fila dela. Por que estamos fazendo isto? Estamos simplesmente dando a um grupo de pedidos consecutivos um date_group comum. Se você executar apenas este CTE, as duas primeiras filas do resultado se parecem com estas: idfirst_namelast_namerow_numberorder_datedate_group 1SimonPaulson12021-10-010 1SimonPaulson22021-10-020 Como você pode ver, Simon Paulson fez pedidos tanto em 1º de outubro quanto em 2 de outubro de 2021. Como eles foram colocados dois dias seguidos, eles pertencem ao mesmo date_group. Como podemos conseguir isto? É o dia extraído do order_date menos o row_number. Na primeira linha, o dia da data '2021-10-01' é 1. O número da linha também é 1. Portanto, é 1-1 = 0, que também é o valor no date_group. A segunda linha é 2-2 = 0, que é o mesmo date_group como acima. O valor específico de date_group realmente não importa! Importa apenas que os dias consecutivos tenham o mesmo valor de date_group. Este é um pequeno truque para calcular a duração de uma série. Funciona porque, se os pedidos são feitos todos os dias, então a diferença entre o número de dias no order_date e o valor no row_number é sempre a mesma para o mesmo cliente. Note que estes dados não aparecem em nenhum lugar. Estou apenas mostrando-os para uma explicação mais fácil do que o CTE faz aqui. É importante mencionar que este truque só funciona se seus dados estiverem todos dentro do mesmo mês. Se a série, digamos, começa em 2021-10-31 e vai até 2021-11-01, o truque não funciona; estes dois dias, embora sejam um após o outro, não pertencerão ao mesmo date_group. Portanto, você tem que entender seus dados antes de decidir usar este truque para obter a duração de uma série. Uma vez que você tenha o CTE, use-o como uma tabela na declaração SELECT. Vou usar a função COUNT() para obter o número dos pedidos em uma linha. Quero ver o resultado para cada cliente, então agrupo os dados por id, first_name, e last_name. Também vou agrupá-los pela coluna date_group, para que os pedidos feitos pelo mesmo cliente sejam separados se houver uma lacuna entre eles. A tabela de resultados idfirst_namelast_nameorders_in_row 1SimonPaulson4 3RebMackennack5 2DylanBobson2 1SimonPaulson1 O Resultado Explicação Esta tabela mostra que Simon Paulson fez quatro pedidos seguidos. Reb Mackennack fez isso cinco dias seguidos, enquanto Dylan Bobson tem apenas dois pedidos seguidos. Finalmente, há um pedido adicional feito por Simon Paulson. Quando os CTEs são úteis? Como você vê nestes exemplos, os CTEs são muito úteis quando você tem que calcular algo em pelo menos duas etapas. Você usa um CTE para preparar o cálculo preliminar, e então você simplesmente usa a declaração SELECT, faz referência ao CTE, e executa outro nível de cálculo. Em cálculos mais complexos, você também pode usar vários CTEs ou mesmo CTEs aninhados. É semelhante a subconsultas, mas os CTEs tornam o código mais legível e mais fácil de dividir o cálculo em etapas. E com os CTEs aninhados, você pode escrever uma consulta e referenciá-la imediatamente como em qualquer outra tabela. Alguns destes exemplos mostram que você também pode usar as funções de agregado e janela. Isto torna os CTEs mais poderosos. Além disso, os CTEs são ótimos para dados hierárquicos como estruturas organizacionais e para atravessar um gráfico. Entretanto, você precisa escrever um CTE recursivo nestes casos, como fiz na pergunta 3. Finalmente, se você quiser escrever consultas recursivas e usá-las, o primeiro passo é aprender os CTEs. Se você precisar de ajuda, aqui está um guia sobre como abordar o aprendizado de CTEs. Como você pode ver, os CTEs têm muitos benefícios e usos práticos. Estes exemplos mostram apenas um vislumbre de soluções para problemas práticos que levam muito mais tempo se não fossem os CTEs. Você quer mais? Não há problema, dê uma olhada em alguns outros usos práticos dos CTEs. Quando você aprender os CTEs e começar a usá-los, tente pensar no problema primeiro. Desdobre as etapas de cálculo e depois traduza esta lógica em um código de expressão comum de tabela SQL. Os CTEs são adequados para isso. Como são uma versão de tabelas temporárias, seja claro ao nomeá-las: use um nome que diga imediatamente o que o CTE faz e seja consistente com as convenções de nomeação. Geralmente, você quer seguir as melhores práticas do CTE, o que torna sua (e outras!) leitura de código muito mais fácil. Quer saber mais sobre as Expressões da Tabela Comum SQL? Se você está se preparando para uma entrevista de emprego SQL, quer ser melhor em seu emprego atual, ou simplesmente quer aprender algo novo em seu tempo livre, dê uma olhada em nosso Consultas Recursivas curso. Lá, você encontra uma abordagem sistemática dos CTEs, explicando a teoria por trás deles, mostrando-lhe a sintaxe e dando-lhe mais alguns exemplos para praticar. O curso inteiro faz parte do SQL Avançado track, que cobre dois tópicos adicionais: funções de janela (que usamos neste artigo) e as extensões GROUP BY. Boa sorte! Tags: sql cte empregos e carreira