diff --git a/content/posts/sql-structured-query-language/sql-structured-query-language.mdx b/content/posts/sql-structured-query-language/sql-structured-query-language.mdx index 4c0563e3..d38dadce 100644 --- a/content/posts/sql-structured-query-language/sql-structured-query-language.mdx +++ b/content/posts/sql-structured-query-language/sql-structured-query-language.mdx @@ -5,11 +5,15 @@ lastUpdate: '2024-05-14T15:14:00.275Z' description: 'Introdução à linguagem SQL e seus principais comandos.' category: 'Article' tags: 'sql,ddl,dml,dcl,database,fapam,gti,postgresql' -status: 'published' +status: 'draft' --- +{/* +[Aula 11](assets/Aula_11_SQL_DML_Parte_3.pdf) +[Comandos Avançados](assets/SQL_Comandos_Avancados.pdf) +*/} - Esse artigo foi feito no intuito de servir como fixação dos conteúdos que estou estudando no momento, ministrado pelo professor **Gabriel Ribeiro Diniz** para as aulas de **Banco de Dados** no curso de [**Gestão de TI - FAPAM**](https://www.fapam.edu.br/graduacao/project/gestao-de-t-i/). + Esse artigo é um resumo feito no intuito de servir como fixação dos conteúdos que estou estudando no momento, ministrado pelo professor **Gabriel Ribeiro Diniz** para as aulas de **Banco de Dados** no curso de [**Gestão de TI - FAPAM**](https://www.fapam.edu.br/graduacao/project/gestao-de-t-i/). # Linguagem SQL @@ -681,6 +685,295 @@ _Resultado:_ |----------|-| | 3 || +### Cláusula `DISTINCT` (linhas únicas) + +Linhas duplicadas podem aparecer nas relações. No caso de desejarmos a eliminação de duplicidade, devemos inserir a palavra `DISTINCT{:sql}` na cláusula `SELECT{:sql}`. + + +**Observações** +- Funções agregadas normalmente consideram as tuplas duplicadas. +- Não é permitido o uso do `DISTINCT{:sql}` com o `COUNT(*){:sql}`. +- É válido usar o `DISTINCT{:sql}` com `MAX{:sql}` ou `MIN{:sql}`, mesmo não alterando o resultado. + + +Tabela neste momento: +```sql +SELECT * FROM peca; +``` +cod_peca | nome_peca | preco | qtd +---|---|---|--- +1 | Peça A | 15.00 | 10 +2 | Peça B | 8.00 | 20 +3 | Peça B | 8.00 | 10 +4 | Peça A | 8.00 | 30 +5 | Peça C | 17.00 | 0 +6 | Peça C | 17.00 | null +7 | Peça A | null | 15 + +**Sinatxe:** + +```sql +SELECT DISTINCT coluna1, coluna2, ... FROM nome_tabela; +``` + +**Exemplo:** + +_Selecionar o nome de todas as peças, sem o `DISTINCT{:sql}`:_ +```sql +SELECT nome_peca FROM peca; +``` +| nome_peca || +|---|-| +| Peça A | +| Peça B | +| Peça B | +| Peça A | +| Peça C | +| Peça C | +| Peça A | + +_Selecionar o nome de todas as peças, com o `DISTINCT{:sql}`:_ +```sql /DISTINCT/ +SELECT DISTINCT nome_peca FROM peca; +``` +| nome_peca || +|---|-| +| Peça C | +| Peça A | +| Peça B | + +### Cláusula `GROUP BY` (agrupar) + +A cláusula `GROUP BY{:sql}` é usada para **agrupar linhas** que possuem o mesmo valor em uma ou mais colunas. É normalmente usada em conjunto com funções de agregação para agrupar os resultados de acordo com um ou mais campos. Desta forma, as funções de agregação será aplicada a **cada grupo**, e não a todas as tuplas. + +Tabela neste momento: +```sql +SELECT * FROM peca ORDER BY nome_peca; +``` +cod_peca | nome_peca | preco | qtd | veiculo +---|---|---|---|--- +1 | Peça A | 15.00 | 10 | CARRO +2 | Peça B | 8.00 | 20 | MOTO +3 | Peça C | 8.00 | 30 | CAMINHAO +4 | Peça D | 8.00 | 10 | CARRO +5 | Peça E | null | 15 | CAMINHAO +6 | Peça F | 17.00 | 0 | MOTO +7 | Peça G | 17.00 | null | CARRO + +**Sintaxe:** + +```sql +SELECT coluna1, coluna2, ... FROM nome_tabela GROUP BY coluna1, coluna2, ...; +``` + +
+ +**EXEMPLO 1** - Selecionar o nome de todas as peças e agrupar por veículo (_contar por grupo_): + +```sql +SELECT veiculo, COUNT(1) FROM peca GROUP BY veiculo; +``` + +_Resultado:_ + +| veiculo | count | +|---|---| +MOTO | 2 +CAMINHAO | 2 +CARRO | 3 + +
+ +**EXEMPLO 2** - Obter a soma da quantidade de peças por tipo de veículo + +```sql +SELECT veiculo, SUM(qtd) FROM peca GROUP BY veiculo; +``` + +_Resultado:_ + +| veiculo | sum | +|---|---| +MOTO | 20 +CAMINHAO | 45 +CARRO | 20 + +### Cláusula `HAVING` (filtro) + +A cláusula `HAVING{:sql}` é usada para **filtrar grupos** de registros que resultam de uma operação de `GROUP BY{:sql}`. A cláusula `HAVING{:sql}` é usada em conjunto com a cláusula `GROUP BY{:sql}`. + +**Sintaxe:** + +```sql +SELECT coluna1, coluna2, ... FROM nome_tabela GROUP BY coluna1, coluna2, ... HAVING condicao; +``` + +**EXEMPLO 2** anterior (_alterado_) - Obter a soma da quantidade de peças por tipo de veículo que sejam maiores que 20 + +```sql /HAVING/ +SELECT veiculo, SUM(qtd) FROM peca GROUP BY veiculo HAVING SUM(qtd) > 20; +``` + +_Resultado:_ + +| veiculo | sum | +|---|---| +CAMINHAO | 45 + +### Seleção com Junção + +As vezes queremos retornar dados de mais de uma tabela, relacionando os dados de uma tabela com os dados de outra. + +Para fazer a junção das tabelas, precisamos definir uma **condição de junção**, na qual os atributos **chave primária** (_primary key_) e **chave estrangeira** (_foreign key_) das relações devem ser relacionados. + +**Tabelas de exemplo** + +
+ +num_tec | nome | cargo +---|---|--- +297 | Marco | Trainee +553 | Hélio | Sênior +062 | Tião | Sênior +718 | Sílvio | Estagiário + + +num_tecnico | tipo | anos_exp +---|---|--- +553 | Secadora | 15 +062 | Lavadora | 18 +297 | Torradeira | 1 +297 | Secadora | 1 +718 | Lavadora | 5 +062 | Congelador | 10 +062 | Secadora | 12 + + +tipo | categoria | taxa +---|---|--- +Lavadora | 1 | 20,00 +Secadora | 1 | 20,00 +Torradeira | 2 | 10,00 +Congelador | 1 | 8,00 +Batedeira | 2 | 25,00 + +
+ +**Exemplo 1:** Obter os nomes dos técnicos com experiência em secadora. + +_Query_ +```sql +SELECT nome FROM tecnicos, experiencia +WHERE num_tec = num_tecnico AND tipo = 'Secadora'; +``` + +_Resultado_ +```console +| Nome | +|-------| +| Hélio | +| Tião | +``` + +**Exemplo 2:** Listar o nome dos técnicos e sua experiência em aparelhos da categoria 1 + +_Query_ +```sql +SELECT tecnicos.nome, experiencia.anos_exp, tipos.tipo +FROM tecnicos, tipos, experiencia +WHERE + tipos.tipo = experiencia.tipo +AND + experiencia.num_tecnico = tecnicos.num_tec +AND + tipos.categoria = 1 +``` + + +Repare que podemos utilizar a sintaxe `tabela.atributo{:sql}` para especificar de qual tabela estamos selecionando o atributo. + +```sql /tecnicos/#b /experiencia/#b /tipos/#b /nome/#g /tipo/#g /categoria/#g /anos_exp/#g /num_tecnico/#g /num_tec/#g caption="Em azul as tabelas e em verde os atributos" +SELECT tecnicos.nome, experiencia.anos_exp, tipos.tipo +FROM tecnicos, tipos, experiencia +WHERE + tipos.tipo = experiencia.tipo +AND + experiencia.num_tecnico = tecnicos.num_tec +AND + tipos.categoria = 1 +``` + + +_Resultado_ + +```console +| nome | anos_exp | tipo | +|--------|----------|-----------| +| Hélio | 15 | Secadora | +| Tião | 18 | Lavadora | +| Marco | 1 | Secadora | +| Sílvio | 5 | Lavadora | +| Tião | 12 | Secadora | +``` + +### Uso de aliases (apelido) + +_Alias_ são **apelidos** que podemos dar aos atributos na hora de retornar valores no `SELECT{:sql}`, permite associar um "nome de variável" para cada relação, a fim de simplificar comandos SQL, e torna o retorno mais legível. + +Para criarmos um _alias_ podemos usar a palavra reservada `AS{:sql}`. Criando um `SELECT{:sql}` com _alias_ temos: + +_Alias para tabelas_ +```sql /AS/ +SELECT T.nome, E.anos_exp, TP.tipo +FROM + tecnicos AS T, + tipos AS TP, + experiencia AS E +WHERE TP.tipo = E.tipo + AND E.num_tecnico = T.num_tec + AND TP.categoria = 1; +``` + +_Alias para atributos_ +```sql /AS/ +SELECT + tecnicos.nome AS Tecnico, + experiencia.anos_exp AS Experiencia, + tipos.tipo AS Tipo +FROM tecnicos, tipos, experiencia +WHERE tipos.tipo = experiencia.tipo + AND experiencia.num_tecnico = tecnicos.num_tec + AND tipos.categoria = 1; +``` +```txt +nome | anos_exp | tipo Tecnico | Experiencia | Tipo +-----|----------|------ --------|-------------|------ + ... | ... | ... ... | ... | ... + ... | ... | ... -> ... | ... | ... + ... | ... | ... ... | ... | ... + ... | ... | ... ... | ... | ... +``` + +### Resumo + +Uma consulta em SQL pode consistir em até seis cláusulas: + +```sql +SELECT [*] [DISTINCT] +FROM +[WHERE ] +[GROUP BY ] +[HAVING ] +[ORDER BY ] [ASC] [DESC] +``` + +**OBSERVAÇÕES** +- Apenas as cláusulas `SELECT{:sql}` e `FROM{:sql}` são obrigatórias +- Quando existentes, as cláusulas devem aparecer na ordem específica acima. +- O `ORDER BY{:sql}` só pode ser ultilizado após o último `SELECT{:sql}` (se a linguagem permitir) +- As cláusulas `GROUP BY{:sql}` e `HAVING{:sql}` só podem ser usadas nos comandos `SELECT{:sql}` individuais + + ## Valores `NULL` (nulo) Suponhamos que temos a tabela `Peça` criada anteriormente, estruturada e preenchida da seguinte forma: @@ -867,139 +1160,36 @@ _Resultado:_ 6 | Peça F | 20.00 | 0 7 | Peça G | 17.00 | null -## Selecionar Dados II - -### Cláusula `DISTINCT` (linhas únicas) - -Linhas duplicadas podem aparecer nas relações. No caso de desejarmos a eliminação de duplicidade, devemos inserir a palavra `DISTINCT{:sql}` na cláusula `SELECT{:sql}`. - -**Observações** -- Funções agregadas normalmente consideram as tuplas duplicadas. -- Não é permitido o uso do `DISTINCT{:sql}` com o `COUNT(*){:sql}`. -- É válido usar o `DISTINCT{:sql}` com `MAX{:sql}` ou `MIN{:sql}`, mesmo não alterando o resultado. +**Artigo em construção...** -Tabela neste momento: -```sql -SELECT * FROM peca; -``` -cod_peca | nome_peca | preco | qtd ----|---|---|--- -1 | Peça A | 15.00 | 10 -2 | Peça B | 8.00 | 20 -3 | Peça B | 8.00 | 10 -4 | Peça A | 8.00 | 30 -5 | Peça C | 17.00 | 0 -6 | Peça C | 17.00 | null -7 | Peça A | null | 15 +{/* -**Sinatxe:** +## Junções (Comando `JOIN`) -```sql -SELECT DISTINCT coluna1, coluna2, ... FROM nome_tabela; -``` +Junção é a possibilidade de se criar relacionamentos entre tabelas, de forma a poder recuperar dados de mais de uma tabela em uma única consulta. Um jeito melhor e nativo de se juntar mais de uma tabela, diferente do método apresentado no capítulo [Seleção com Junção](#seleção-com-junção). -**Exemplo:** +Isso é possível atravez do comando `JOIN{:sql}` (_junção_), que é usado para combinar linhas de duas ou mais tabelas com base em uma relação entre elas, e recuperando esses dados usando apenas um `SELECT{:sql}`. -_Selecionar o nome de todas as peças, sem o `DISTINCT{:sql}`:_ -```sql -SELECT nome_peca FROM peca; -``` -| nome_peca || -|---|-| -| Peça A | -| Peça B | -| Peça B | -| Peça A | -| Peça C | -| Peça C | -| Peça A | +É importante utilizá-lo, porque tira da cláusula `WHERE{:sql}` condições que são estritamente das junções (chave primária igual a chave estrangeira, por exemplo). -_Selecionar o nome de todas as peças, com o `DISTINCT{:sql}`:_ -```sql /DISTINCT/ -SELECT DISTINCT nome_peca FROM peca; -``` -| nome_peca || -|---|-| -| Peça C | -| Peça A | -| Peça B | - -### Cláusula `GROUP BY` (agrupar) - -A cláusula `GROUP BY{:sql}` é usada para **agrupar linhas** que possuem o mesmo valor em uma ou mais colunas. É normalmente usada em conjunto com funções de agregação para agrupar os resultados de acordo com um ou mais campos. Desta forma, as funções de agregação será aplicada a **cada grupo**, e não a todas as tuplas. - -Tabela neste momento: -```sql -SELECT * FROM peca ORDER BY nome_peca; -``` -cod_peca | nome_peca | preco | qtd | veiculo ----|---|---|---|--- -1 | Peça A | 15.00 | 10 | CARRO -2 | Peça B | 8.00 | 20 | MOTO -3 | Peça C | 8.00 | 30 | CAMINHAO -4 | Peça D | 8.00 | 10 | CARRO -5 | Peça E | null | 15 | CAMINHAO -6 | Peça F | 17.00 | 0 | MOTO -7 | Peça G | 17.00 | null | CARRO - -**Sintaxe:** - -```sql -SELECT coluna1, coluna2, ... FROM nome_tabela GROUP BY coluna1, coluna2, ...; -``` - -
- -**EXEMPLO 1** - Selecionar o nome de todas as peças e agrupar por veículo (_contar por grupo_): - -```sql -SELECT veiculo, COUNT(1) FROM peca GROUP BY veiculo; -``` - -_Resultado:_ - -| veiculo | count | -|---|---| -MOTO | 2 -CAMINHAO | 2 -CARRO | 3 +Existem as variações de junções **internas** e **externas**. -
- -**EXEMPLO 2** - Obter a soma da quantidade de peças por tipo de veículo +**Internas**: `INNER JOIN{:sql}` e `NATURAL JOIN{:sql}` -```sql -SELECT veiculo, SUM(qtd) FROM peca GROUP BY veiculo; -``` - -_Resultado:_ - -| veiculo | sum | -|---|---| -MOTO | 20 -CAMINHAO | 45 -CARRO | 20 - -### Cláusula `HAVING` (filtro) - -A cláusula `HAVING{:sql}` é usada para **filtrar grupos** de registros que resultam de uma operação de `GROUP BY{:sql}`. A cláusula `HAVING{:sql}` é usada em conjunto com a cláusula `GROUP BY{:sql}`. + +A palavra `INNER{:sql}` pode ser omitida + -**Sintaxe:** +**Como funciona o comando `JOIN{:sql}`?** -```sql -SELECT coluna1, coluna2, ... FROM nome_tabela GROUP BY coluna1, coluna2, ... HAVING condicao; -``` +Quando um comando `SELECT{:sql}` especifica campos de duas tabelas **sem nenhumas restrição ou filtro**, o resultado será um número de linhas iguais à multiplicação do total de linhas da primeira tabela ($N$) pela segunda tabela ($M$), ou seja $M\times N$. -**EXEMPLO 2** anterior (_alterado_) - Obter a soma da quantidade de peças por tipo de veículo que sejam maiores que 20 +Isso ocorre devido ao fato de que, para cada linha da primeira tabela, todas as linhas da segunda são processadas. Operações de junção toma duas relações, e têm como resultado uma outra relação. -```sql /HAVING/ -SELECT veiculo, SUM(qtd) FROM peca GROUP BY veiculo HAVING SUM(qtd) > 20; -``` +**Funcionamento do comando `JOIN{:sql}` -_Resultado:_ +_Pág. 11_ -| veiculo | sum | -|---|---| -CAMINHAO | 45 +*/}