Escolar Documentos
Profissional Documentos
Cultura Documentos
Introdução
Sobre Este Tutorial
Este é o primeiro de uma série de dois documentos provendo uma introdução/revisão dos princípios
básicos e conceitos da linguagem SQL, objetivando capacitar o leitor a escrever suas próprias
consultas.
Apesar de concebido como material de suporte para o curso BlockSQL, a ser lido pelos alunos,
instrutores, monitores e convidados do curso, este documento adota uma abordagem genérica, com
exemplos próprios, distintos do resto do curso. Isso foi feito para tornar esse texto tão sucinto,
objetivo, autocontido e reaproveitável quanto possível. As particularidades do banco de dados
principal do curso serão tratadas em outro documento.
Contudo, esse texto não pretende ser um curso completo de SQL; ele vai se ater apenas ao mínimo
necessário para acompanhar o curso BlockSQL. Existem vários livros, vídeos e cursos disponíveis
que cobrem o assunto em muito mais amplitude e profundidade.
Recomendamos que o leitor execute as consultas usadas como exemplo no banco de dados e confira
pessoalmente os resultados. Entre em contato com seu instrutor ou os monitores para obter as
informações de acesso.
À época em que este documento foi escrito, estava na moda usar o ChatGPT para explicar o que as
consultas fazem (“traduzi-las para Português”) ou para escrever as consultas para nós. Como todas
as consultas feitas aqui são muito básicas, o ChatGPT não tem dificuldade em entendê-las, explicá-
las ou fazê-las. Por essa mesma razão, as explicações dele não nos pareceram muito melhores do
que as que já estão contidas nesse documento.
1/20
Todavia, como a linguagem evoluiu em direções muito além desse objetivo, a tentativa de fazê-la
resultar em “frases legíveis em inglês” ficou em segundo plano. Mesmo assim, veremos que muitos
comandos e cláusulas da linguagem são, de fato, trechos de frases em inglês, quase sempre
começando com um verbo no imperativo e pensando no resto da frase como um monte de adjetivos
e conectivos.
Mas é por causa dessa história que, até hoje, muitos falantes nativos da língua inglesa pronunciam
“SQL” como “síquel”, ao invés das letras individuais da sigla: “éss-kíu-él”. Os brasileiros
pronunciam “ésse-quê-éli” mesmo.
A linguagem SQL é uma das mais antigas, tradicionais e bem estabelecidas da informática – a
primeira versão apareceu em 1974 e foi padronizada em 1986 pela ANSI (a equivalente americana
à nossa ABNT) e pela ISO (Organização Internacional de Padrões) no ano seguinte.
A linguagem SQL não é uma “linguagem de programação completa” ao estilo das linguagens mais
populares, como JavaScript, Python, C, C++, Flutter, Rust, etc. Isso tem a vantagem de torná-la
muitíssimo mais fácil de aprender e dominar. Em particular, a linguagem SQL descreve o que você
quer que seja feito, sem explicitar como será feito – descobrir “como fazer” é exatamente o trabalho
do sistema de banco de dados. Mesmo assim, a desenvoltura com a linguagem SQL não só é muito
importante para diversos trabalhos no mundo da informática, mas também é um excelente passo
intermediário para quem quer aprender a programar.
Dominar a linguagem, porém, é apenas um dos conhecimentos que se precisa. É também essencial
conhecer a estrutura dos dados, seus significados, suas origens, quem os fornece e quem os usa.
Fazendo uma analogia, dominar SQL é como aprender a dirigir; conhecer os dados é como
conhecer as ruas, caminhos e lugares de uma cidade. É perfeitamente possível saber dirigir e não
conseguir chegar a lugar nenhum porque não se conhece os caminhos; e é perfeitamente possível
conhecer os caminhos sem saber dirigir. Os melhores resultados são obtidos quando se combina os
dois tipos de conhecimento.
2/20
Conceitos Básicos
A unidade básica de armazenamento e organização das informações em um banco de dados
relacional chama-se tabela. O termo “relação” é um termo antigo para “tabela” – é por isso que esse
tipo de banco de dados se chama “relacional”: nesse contexto, “relacional” quer dizer “baseado em
tabelas”. Existem outros tipos de bancos de dados baseados em outros princípios.
As tabelas são arranjos regulares de informações em linhas e colunas. O termo “registro” é um
sinônimo antigo, mas ainda muito em uso, para “linha”; e o termo “campo” é um termo antigo, mas
ainda muito em uso, para “coluna”. Cada campo tem um nome para que possamos nos referir a cada
uma delas individualmente. Cada “retângulozinho” nos pontos de encontro entre as linhas e colunas
chama-se célula, e cada célula tem dentro de si um valor ou conteúdo. A figura abaixo provê um
exemplo de como se parece visualmente uma tabela contendo dados sobre países:
Tabela “Countries”
cabeçalho
code name capital population area com nomes
BR Brasil Brasília 217240060 8515767 das colunas
AR Argentina Buenos Aires 46044703 2780400
CL Chile Santiago 18430408 756096 linhas
colunas
As tabelas podem ser de vários tipos, como as tabelas materializadas, que têm nome (como a
tabela “Countries” do exemplo acima), armazenam dados, ocupam espaço no HD ou SSD do
computador onde o banco de dados está hospedado, são feitas para durar indefinidamente e cujos
dados servem de origem para consultas posteriores; ou as tabelas efêmeras, que só existem por um
curto período de tempo e depois são descartadas.
Consultas Básicas
Digite a seguinte consulta e a execute, clicando no botão “Play”:
SELECT 1
(colocamos as palavras estruturais da linguagem SQL em negrito só para facilitar a leitura; digite-as
normalmente.)
O resultado será uma tabela como a abaixo:
1
1
A primeira linha na tabela acima é o cabeçalho com os nomes dos campos. Esse “1” que aparece
nessa primeira linha é o nome do campo. Os nomes dos campos normalmente são textos bem curtos
3/20
descrevendo seus significados, mas, na realidade, podem ser qualquer coisa, inclusive números,
como no exemplo acima.
Quando você não explicita o nome do campo, o ClickHouse inventa um a partir do contexto. Nesse
caso, como o único contexto que ela tinha era o número “1” que você digitou na consulta, ele usou
isso como nome de campo.
O resultado das consultas aparece nas linhas após a primeira. No caso dessa consulta, o resultado
tem apenas uma linha e uma coluna, e o seu conteúdo é “1”.
As tabelas que resultam das consultas são efêmeras (seu conteúdo não fica guardado e é descartado
logo depois) e anônimas (elas não têm nome).
O resultado será, novamente, uma tabela de uma única linha e uma única coluna:
valor
1
Mas, como podemos ver, a coluna recebeu o nome que especificamos após a cláusula “AS” (a
palavra “como”, em inglês). Esse nome da coluna é chamado de alias (a pronúncia correta em
inglês é “êiliéss”, mas os brasileiros frequentemente dizem “álias”, “aliás”, ou “alías”.)
Tecnicamente, a cláusula “AS” é opcional – ela pode ser omitida:
SELECT 10 valor
valor
10
Se o nome do campo for uma única palava (isto é, não contiver espaços), começar com uma letra e
não tiver acentos ou sinais de pontuação, pode-se escrevê-lo diretamente, como fizemos acima.
Contudo, podemos ter nomes de campos quaisquer, se colocarmos seus nomes dentro de aspas
duplas, como no exemplo abaixo:
SELECT 1 AS "Valor Resultante"
O resultado será:
Valor Resultante
1
Podemos até mesmo ter nomes de campos contendo o próprio caractere “aspas duplas”: para isso,
devemos grafar duas aspas duplas, para que o sistema possa diferenciar o início e o fim do nome
pelas aspas sozinhas, e onde queremos aspas através das aspas duplas em dobro:
4/20
SELECT 1 AS "Valor ""especial"" resultante"
O resultado será:
Valor "especial" resultante
1
Dar bons nomes aos campos é uma arte: o ideal é ser sucinto, preferindo nomes curtos que
economizem digitação; mas é igualmente importante dar nomes que comuniquem o significado da
informação da forma mais clara possível. Neste curso, além desses princípio gerais, vamos adotar
os seguintes convenções:
• expressões em inglês (preferivelmente uma palavra só) descrevendo sucintamente que
informação o campo guarda – isso ajuda quando se trabalha com equipes internacionais;
• sempre em letras minúsculas;
• se forem mais de uma palavra, colocaremos o caractere de sublinhado (“_”, chamado de
“underline”, em inglês) onde se colocaria o espaço – isso nos permite evitar usar aspas duplas;
As operações aritméticas que aprendemos na escola são representadas pelos seguintes símbolos:
Os sinais de pontuação tradicionais são uma conveniência que o ClickHouse nos oferece para
escrevermos as expressões da forma que estamos acostumados. Mas, internamente, ele converte
todas as expressões para a chamada forma funcional, em que todas as operações são transformadas
em chamadas para funções, que são operações pré-determinadas e que têm um nome. Para “chamar
uma função” (ou seja, pedir que ela calcule algo), você deve colocar cada um dos dados que ela
precisa separados por vírgulas e englobados entre parênteses. Então, a na forma funcional, a
operação 1+1 acima fica:
5/20
plus(1,1)
De fato, quando você escreve uma expressão e não especifica um nome para seu respectivo campo,
o ClickHouse usa a forma funcional como nome do campo.
➢ Cada banco de dados tem seu jeito próprio de dar nomes automáticos aos campos: o
PostgreSQL, por exemplo, usa ?column? quando a consulta não especifica um nome, e o
MariaDB usa a própria expressão que deu origem ao campo.
Pode-se perfeitamente digitar plus(1,1) diretamente na consulta:
SELECT plus(1,1)
Operações com vários termos são perfeitamente aceitas e se tornam funções aninhadas:
SELECT 1+2+3
Resulta em:
plus(plus(1, 2), 3)
6
Repare não só no resultado correto, o número seis, mas também na forma funcional da expressão
que apareceu como nome do campo: a função plus foi usada duas vezes e os parênteses estão
aninhados (parêntese dentro de parêntese).
Sob essa interpretação, o primeiro argumento da primeira função plus é outra função plus com
argumentos um e dois; e o segundo argumento da primeira função plus é o número três. Note ainda
o posicionamento dos parênteses: há um abre-parêntese sempre imediatamente após o nome da
função e um fecha parêntese após o último argumento.
Tal como aprendemos no colégio, as expressões entre parênteses mais internos são executadas
primeiro. No exemplo acima, a primeira coisa a ser calculada é o plus(1,2), que resulta em 3. O
resultado ocupa o lugar de onde o plus(1,2) estava, então a expressão inteira se reduz a
plus(3,3), cujo resultado é seis.
Eis outro exemplo onde os parênteses se comportam como aprendemos na escola: calcular a média
entre 10 e 8:
SELECT (10+8)/2
O resultado é:
divide(plus(10, 8), 2)
9
6/20
Precisamos colocar o parêntese para que a soma fosse executada antes da divisão, pois, tal como
aprendemos na matemática, normalmente as divisões e multiplicações são executadas primeiro. Isso
fica bem claro se experimentarmos não colocar os parênteses:
SELECT 10+8/2
Se nossa intenção era calcular a média, o resultado acima estaria errado. Mas, uma das vantagens da
forma funcional é que ela deixa muito clara a ordem exata em que as funções são aplicadas.
No ClickHouse, quase tudo é feito através de funções. Muitas funções têm operadores equivalentes,
tal como o operador + (sinal de mais) é equivalente à função plus, o * (asterisco) é a operação de
multiplicação e equivalente à função multiply, etc. Existem vários outros operadores que vamos
conhecer mais adiante, e todo operador tem uma função correspondente.
O contrário, porém, não é verdade: nem toda função tem um operador correspondente; há muitos
recursos que só são disponibilizados na forma de funções.
No ClickHouse, a operação de divisão pode dar resultados fracionários mesmo se os dois operandos
forem inteiros.
SELECT 5/2
divide(5, 2)
2.5
Note o uso dos parênteses aninhados. Em SQL, os símbolos de colchetes e chaves tem outros
significados que veremos mais adiante.
7/20
Note que, para uma expressão ser válida, os parênteses devem estar balanceados: deve haver a
mesma quantidade de “fecha parênteses” que de “abre parênteses”. Se a houver mais parênteses
abrindo do que fechando ou o contrário, você receberá uma mensagem de erro tipo
“SYNTAX_ERROR”.
Expressões Textuais
Além de números, os valores podem ser textos. Dentro de uma consulta SQL, os textos são trechos
entre aspas simples:
SELECT 'Alô Mundo!'
'Alô Mundo!'
Alô Mundo
Novamente, a primeira linha acima é a linha de cabeçalhos, indicando que o nome do campo é . A
segunda linha é o resultado em si, que é o texto, sem as aspas simples.
Tal como antes, podemos dar os nomes que quisermos aos campos:
SELECT 'Alô Mundo!' AS "Saudação"
Saudação
Alô Mundo
O exemplo acima ainda serve para ilustrar a diferença entre as aspas simples e aspas duplas:
• Aspas Simples: delimitam valores textuais. Em Ciência da Computação, valores textuais são
chamados de “strings” (abreviatura de “character string” ou “cadeia de caracteres”). Atente que
o caractere “aspas simples” não é o mesmo que o acento agudo; nos teclados padrão ABNT2
usados aqui no Brasil, ele fica à esquerda do numeral 1.
Há que use o termo “apóstrofo” como sinônimo para “aspas simples”, mas, na realidade, são
dois caracteres diferentes: os apóstrofos são curvados, e as aspas simples são retas.
• Aspas Duplas: delimitam nomes de campos ou nomes de tabelas. Nos teclados ABNT2 usados
aqui no Brasil, a aspas dupla também fica à esquerda do numeral 1, mas requer o uso simultâneo
da tecla SHIFT.
Atente que alguns editores de texto, como o Google Docs, LibreOffice Writer e o Microsoft
Word trocam as aspas duplas " (note que os tracinhos são retos) por aspas tipográficas “ ” (abre
e fecha aspas, respectivamente; note como elas são curvadas) ao digitar. É preciso dar o
comando de desfazer (teclas CTRL-Z) imediatamente após digitá-la para o editor de texto
reverter para as aspas retas (isso também funciona com as aspas simples).
Um sinônimo popular para as aspas duplas são as aspas invertidas: ` (no teclado ABNT2, as
aspas invertidas é feita pressionando SHIFT + acento agudo, para fazer uma acento grave, e
imediatamente em seguida pressionando a barra de espaço).
8/20
Confundir o uso das aspas simples com aspas duplas é considerado um erro amador embaraçoso!
(embora até os profissionais se confundem às vezes, pois diferentes linguagens de programação têm
diferentes significados para os vários tipos de aspas).
Caso o próprio texto que queiramos utilizar contenha aspas simples, podemos especificá-la usando
duas aspas simples (que, dependendo da fonte e do zoom da tela, podem acabar ficando parecidas
com uma aspas dupla!):
SELECT 'Pingo d''água' AS texto
texto
Pingo d'água
Perceba que a primeira e a última aspas delimitam o início e o fim do texto, e as aspas simples
repetidas (que não é a mesma coisa que aspas duplas!) fazem as vezes de uma única aspas simples
dentro do texto.
Os textos são considerados valores como outros quaisquer, e é possível fazer cálculos e expressões
com eles. Por exemplo, o operador || (duas barras verticais; também chamado de “pipe pipe” –
pronuncia-se “paipe paipe”) realiza uma operação chamada concatenação, que consiste em
emendar dois textos um seguido do outro:
SELECT 'Recife,' || 'Brasil' AS texto
texto
Recife,Brasil
No exemplo acima, note que não há espaço entre a vírgula e o “Brasil”. O operador de concatenação
não acrescenta nenhum caractere que não tenha sido explicitamente colocado; por isso, se
quisermos que não fique “grurado”, temos de colocar explicitamente o espaço:
SELECT 'Recife,' || ' Brasil' AS texto
texto
Recife,Brasil
Vale aqui uma advertência importante: os navegadores (Chrome, Firefox, etc.) colapsam múltiplos
espaços seguidos em um só ao exibir textos. Por exemplo, se você executar a consulta abaixo:
SELECT 'Curso ' || ' BlockSQL' AS texto
O resultado correto terá dois espaços (um após o “o” final da palavra “Curso” e outro antes do “B”
inicial da palavra “BlockSQL”). Mas, se você selecionar o texto na tela do navegador e copiá-lo,
digamos, para o Bloco de Notas, vai aparecer apenas um espaço entre as duas palavras. Esse é um
“erro” causado pelo navegador, não pelo banco de dados.
Experimente refazer as consultas acima sem definir o nome do campo, de forma que o ClickHouse
lhe mostre a forma funcional – você verá que o nome da função que corresponde ao operador || é
concat.
9/20
Múltiplas Colunas
Pode-se criar uma tabela com vários colunas separando-as por vírgulas:
SELECT 10 AS "Número", 'Tempus Fugit' AS "Citação", 3+3 AS soma
Observe que a ordem das colunas na tabela resultante é a mesma em que elas são listadas na
consulta. Então, por exemplo, se quiséssemos que a citação aparecesse primeiro, bsataria colocá-la
antes dos demais campos:
SELECT 'Tempus Fugit' AS "Citação", 10 AS "Número", 3+3 AS soma
Note que o último campo é o único que não é seguido de vírgula e é isso que indica que a lista de
campos acabou. Sempre que houver uma vírgula após a descrição de um campo, o ClickHouse
entenderá que há outro campo a seguir.
Um erro muito comum oriundo disso é, ao copiar-e-colar para rearranjar a ordem dos campos,
deixar uma vírgula sobrando no final:
SELECT 1 AS campo1, 2 AS campo2,
10/20
name population
Brasil 217240060
Chile 18430408
Argentina 46044703
Quando você especifica o nome de uma tabela na cláusula FROM, o banco de dados vai de linha em
linha daquela tabela e gera uma nova tabela com os campos que você pediu na seção entre o SELECT
e o FROM. No exemplo, colocamos o nome entre aspas, mas, como ele não tem espaços nem acentos,
omitiremos as aspas daqui em diante.
É possível pedir todos os campos da tabela sem explicitar seus nomes usando o caractere
“asterisco”, que vale como um “curinga”, como no exemplo abaixo:
SELECT * FROM Countries
Isso resulta na exibição da tabela completa, incluindo todos as linhas e todos as colunas:
code name capital population area
AR Argentina Buenos Aires 46044703 2780400
BR Brasil Brasília 217240060 8515767
CL Chile Santiago 18430408 756096
Experimente repetir essa consulta algumas vezes. Você notará que os dados podem não vir sempre
na mesma ordem, mas todas as linhas da tabela sempre virão.
Os campos de uma consulta que são obtidos da mera citação direta do nome de uma tabela, ou
através do asterisco, como fizemos nos exemplos acima, são chamados de campos literais.
Podemos ter também os chamados campos calculados, que usam as expressões numéricas e de
textos para calcular resultados oriundos de um ou mais campos literais da tabela. Por exemplo, se
quisermos ter uma lista com as densidades populacionais dos países, poderíamos fazer uma consulta
assim:
SELECT
name || ' (' || code || ')' AS country,
population/area AS population_density
FROM Countries
Para tornar a consulta mais fácil de ler, nós a partirmos em várias linhas, e acrescentamos espaços
extras para alinhar as cláusulas “AS” de modo a ficarem umas embaixo das outras. Isso facilita ler
os nomes dos campos e suas definições. Você pode digitar (ou copiar-e-colar) a consulta assim
mesmo: o banco de dados não se incomoda com espaços ou quebras de linha extras.
Recomendamos que você adote essa prática, pois é muito comum fazer consultas extensas que
ficam muito ruins de ler se colocadas em uma linha só.
O resultado dessa consulta é:
11/20
country population_density
Brasil (BR) 25.51033394877995
Chile (CL) 24.375751227357373
Argentina (AR) 16.560460005754567
Note como usamos uma expressão textual para colocar o código do país entre parênteses no
resultado final, separado do nome por um espaço. E note também como usamos uma expressão
numérica para dividir a população do país por sua área para obter a densidade populacional.
Também é perfeitamente possível misturar campos literais com calculados.
O banco de dados não tem noção das unidades de medida que utilizamos. Em lugar nenhum está
dito, por exemplo, que a área está em quilômetros quadrados e que a população está em habitantes.
Tem gente que gosta de acrescentar essa informação no nome dos campos:
SELECT
name || ' (' || code || ')' AS country_and_code,
population/area AS population_density_in_square_km
FROM Countries
country_and_code population_density_in_square_km
Brasil (BR) 25.51033394877995
Chile (CL) 24.375751227357373
Argentina (AR) 16.560460005754567
O banco de dados também não tem noção do significado dos dados, nem do contexto do que o
usuário quer saber, ou do problema que quer resolver; e não vai entender, muito menos questionar,
se o que o usuário pediu faz sentido. Por exemplo, se, ao invés de dividir a população pela área,
fosse feito uma soma, o banco de dados executaria a consulta sem problema nenhum, mas o
resultado seria totalmente espúrio. A função do analista de dados é justamente entender o contexto,
os dados, fazer as perguntas e contas certas, bem como conferir e criticar os próprios resultados para
ver se fazem sentido.
O que aconteceu aqui é que, para cada linha, a condição especificada no WHERE é testada com os
valores das colunas daquela linha. Ao passar pela linha que continha os dados do Brasil, o banco
12/20
de dados viu que o valor do campo area satisfazia a condição de ser maior que um milhão. O
mesmo aconteceu para a linha seguinte, com os dados da Argentina. Contudo, ao chegar na linha
com os dados do Chile, a condição não era verdadeira, então essa linha foi omitida do resultado
(embora continue intacta na tabela Countries original).
É perfeitamente possível definir critérios baseados em campos calculados, como o exemplo abaixo
mostra:
SELECT
name || ' (' || code || ')' AS country_and_code,
population/area AS population_density_in_square_km
FROM Countries
WHERE population_density_in_square_km < 20
country_and_code population_density_in_square_km
Argentina (AR) 16.560460005754567
É também perfeitamente possível especificar uma condição que nenhuma linha satisfaça, resultando
em uma tabela vazia (sem nenhuma linha de conteúdo, a não ser pelo cabeçalho):
SELECT * FROM Countries WHERE code = 'XX'
Um resultado vazio pode ser exatamente o que se deseja – por exemplo, quando estamos
interessados em saber que um certo caso não ocorre. Às vezes um resultado vazio pode ser
inesperado e nos assustar momentaneamente, mas cabe a nós avaliar se a consulta está certa e o
resultado vazio faz sentido, ou se o resultado veio vazio porque erramos algo na consulta.
Para especificar condições, usamos os chamados operadores relacionais:
Observe que a operação “diferente de” tem duas grafias. A primeira é mais tradicional, e a segunda
foi criada porque quase todas as linguagens de programação usam dessa forma.
Os operadores relacionais retornam o número zero se a condição for falsa ou o número um se a
condição for verdadeira. O ClickHouse até tem as palavras-chave true e false, mas elas são
apenas apelidos para os valores numéricos um e zero, respectivamente.
Alguns exemplos:
13/20
SELECT 5 > 3
greater(5, 3)
1
O fato de ter retornado 1 (“true”, ou “verdadeiro”, em Português) deve ser interpretado como: “sim,
cinco é realmente maior que três”.
SELECT 5 < 3
less(5, 3)
0
O fato de ter retornado zero (“false”, ou “falso”, em Português) deve ser interpretado como: “não,
cinco não é menor que três”.
Como vimos acima, os operadores relacionais funcionam não só pra números, mas para textos,
também:
SELECT 'X' || 'Y' = 'XY'
Para dois textos serem considerados iguais, os textos têm de ser idênticos letra a letra: eles têm de
ter exatamente a mesma quantidade de caracteres e exatamente os mesmos caracteres, nas mesmas
posições. É o que aconteceu no exemplo acima: o resultado da concatenação de ‘X’ com ‘Y’ é
‘XY’, que é idêntico ao ‘XY’ do lado direito da igualdade.
Note que letras maiúsculas são consideradas distintas das letras minúsculas:
SELECT 'ab' = 'AB'
equals('ab', 'AB')
0
Caracteres acentuados também são considerados diferentes das suas versões com acentos:
SELECT 'c' ='ç'
equals('c', 'ç')
0
Um texto é considerado maior que o outro se o caractere na mesma posição nos dois textos vem um
depois após o outro na tabela Unicode – ela é grande demais para incluir neste texto, mas, pelo
14/20
menos para os caracteres mais comuns, dá pra sintetizar na tabela abaixo (o primeiro elemento da
primeira linha é o caractere “espaço”):
! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
@ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _
` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
Se o caractere for idêntico, o desempate é feito aplicando esse critério ao próximo caractere. Se esse
era o último caractere, o texto mais longo é considerado o maior. Se os dois textos são do mesmo
tamanho e têm os mesmos caracteres em todas as posições, eles são considerados iguais, como já
visto acima. Exemplo:
SELECT 'B' > 'AB'
greater('B', 'AB')
1
Outro exemplo:
SELECT 'ABA' > 'AB'
greater('ABA', 'AB')
1
Um detalhe curioso na tabela acima é que as letras maiúsculas são consideradas “menores” que as
minúsculas:
SELECT 'A' < 'a'
less('A', 'a')
1
less('9', 'A')
1
Às vezes precisamos especificar múltiplas condições. Nesse caso, precisamos conectá-las usando os
chamados operadores lógicos:
15/20
SELECT * FROM Countries WHERE area >= 1000000 AND population >= 100000000
Dentre os apenas três países que constam na tabela, só o Brasil satisfaz simultaneamente as duas
condições: ter mais de um milhão de quilômetros quadrados e mais de cem milhões de habitantes. A
Argentina até satisfaz a primeira condição, mas não a segunda; e o Chile não satisfaz nenhuma das
duas, e, por isso, não aparece.
Trocando o AND por OR, teríamos:
SELECT * FROM Countries WHERE area >= 1000000 OR population >= 100000000
Nesse caso, basta o país satisfazer qualquer uma das condições para ser incluso; para ficar de fora,
ele precisa não satisfazer nenhuma das condições, que é o que acontece com o Chile.
Já o exemplo abaixo nos dá a lista de países do mais populoso para o menos populoso:
SELECT * FROM Countries ORDER BY population DESC
E a consulta abaixo nos dá os países com os nomes em ordem alfabética (o SQL assume “ ASC” se o
omitirmos, como fizemos abaixo):
SELECT * FROM Countries ORDER BY name
16/20
code name capital population area
AR Argentina Buenos Aires 46044703 2780400
BR Brasil Brasília 217240060 8515767
CL Chile Santiago 18430408 756096
O critério de ordenação secundário (em ordem decrescente de população, nesse exemplo) seria
acionado caso houvesse algum empate no critério primário (dois países com o mesmo nome). Nessa
tabela de exemplo, isso não faria diferença porque não há dois países com o mesmo nome.
É perfeitamente possível combinar WHERE com ORDER BY, lembrando apenas que o WHERE vem logo
após o FROM e o ORDER BY vem por último:
SELECT * FROM Countries WHERE area < 3000000 ORDER BY name
A cláusula LIMIT encerra a consulta assim que a quantidade de linhas atinge a quantidade de
elementos desejada. Por exemplo, a consulta abaixo só mostrará apenas uma linha:
SELECT * FROM Countries LIMIT 1
Mas lembre-se que, a menos que explicitamente imponhamos uma ordem, a linha exata que vai vir
acima pode variar (ou não! – se a tabela for pequena, quase sempre o ClickHouse começa sempre
no mesmo ponto; além disso, algumas tabelas do ClickHouse são estruturadas de uma forma que
impõe ordem naturalmente – o comportamento exato depende do tipo de tabela, como ela foi criada
e que índices ela tem.)
A cláusula OFFSET pula uma certa quantidade de linhas do início dos resultados. Por exemplo, a
consulta abaixo pula a primeira linha e limita o resultado total apenas a uma linha, resultado em
obter a segunda linha da tabela:
SELECT * FROM Countries LIMIT 1 OFFSET 1
17/20
code name capital population area
BR Brasil Brasília 217240060 8515767
Pode-se perfeitamente combinar a clásula LIMIT com ORDER BY e WHERE, lembrando que o WHERE
fica logo após o FROM, o OFFSET fica por último, o LIMIT fica antes do OFFSET e o ORDER BY fica
antes do LIMIT. O ClickHouse emite um erro de sintaxe se essa ordem não for respeitada.
capital lengthUTF8(capital)
Buenos Aires 12
Brasília 8
Santiago 8
A linguagem SQL, porém, define certas funções, chamadas funções de agregação, que calculam
resultados usando todos valores em todas as linhas da coluna especificada. Por exemplo, para
calcularmos a população total dos países, poderíamos usar a função sum (“soma”, em inglês):
SELECT sum(population) FROM Countries
sum(population)
281715171
18/20
avg(area) AS media
FROM Countries
Note que, na consulta acima, usamos a função de agregação count (“contagem”, em inglês) com a
lista de argumento vazia (nada entre os parênteses). Ela tem a particularidade de não precisar de
argumentos porque ela mede a quantidade de linhas, independente de qual coluna seja. Não teria
dado erro se tivéssemos colocado count(area) ao invés de count(), mas também não faria
diferença.
O nome da função avg é abreviatura do termo em inglês “average”, que significa média. O nome
max é abreviatura de “maximum” (“máximo”), e min é abreviatura de “minimum” (“mínimo”).
Sempre que há uma função de agregação em uma consulta, a tabela resultante terá apenas uma linha
por grupo; como não especificamos um agrupamento (veremos como fazer isso na segunda parte
deste tutorial), o grupo fica sendo a tabela inteira, de sorte que o resultado terá uma linha só.
Isso significa que não é possível combinar agrupamentos e campos normais em uma mesma
consulta, pois a coluna da função de agregação resultam uma linha só, enquanto as demais resultam
em tantas linhas quanto a tabela tiver – não dá para uma tabela ser irregular, com quantidades de
linhas diferentes para cada coluna. Por exemplo, a seguinte consulta:
SELECT name, max(area) FROM Countries
A mensagem de erro é até bem esclarecedora: ela explica bem direitinho que a coluna name não está
sob agregação, nem em uma cláusula GROUP BY (que a tornaria permitida porque seu valor seria
único por grupo), e ainda lista a agregação que deu origem à situação: max(area).
Se a intenção da consulta acima era descobrir qual o país que tem a maior área, há uma função de
agregação chamada argMax que faz isso:
SELECT argMax(name,area), max(area) FROM Countries
argMax(name,area) max(area)
Brasil 8515767
Note que a função argMax tem dois parâmetros: o primeiro diz qual campo cujo valor você
realmente quer, e o segundo diz qual o campo ela vai usar para achar a linha que tem o maior valor.
Como você pode imaginar, existe uma função argMin também. Um detalhe importante: se vários
itens tiverem o mesmo valor máximo ou mínimo, a função escolhe um deles a esmo (em geral, o
primeiro deles).
19/20
➢ As funções argMin e argMax são específicas do ClickHouse.
Em Caso de Erro
Confira:
• Que não esteja faltando alguma vírgula entre os nomes dos campos entre o SELECT e o FROM;
• Que não tenha uma vírgula sobrando após o último campo;
• Que todos as abre aspas (smples ou duplas) têm um fecha aspas correspondente e do mesmo
tipo;
• Que os parênteses estejam corretamente aninhados e balanceados (todo “abre parêntese” deve
ter um fecha parêntese correspondente)
• Que os nomes dos campos e das tabelas estejam grafados corretamente;
➢ Especial atenção ao caractere _ (“sublinhado”), que às vezes “desaparece” quando se dá
zoom no navegador, dando a impressão que é um espaço, ao invés.
• Que os nomes das palavras-chave da linguagem SQL ( SELECT, FROM, ORDER BY, LIMIT, OFFSET)
estejam grafados corretamente e na ordem certa;
• Leia o texto descritivo do erro. Por vezes ele dá boas pistas do que pode estar errado.
20/20