Mostrando postagens com marcador SQL. Mostrar todas as postagens
Mostrando postagens com marcador SQL. Mostrar todas as postagens

quinta-feira, 1 de outubro de 2020

Juntando tabelas em uma base de dados relacional com SQL

Photo by Tim Johnson on Unsplash

No primeiro post sobre a linguagem SQL fomos apresentados ao conceito de bancos de dados relacionais e a um aplicativo que nos possibilita armazenar dados em tabelas relacionadas. Nessas tabelas os dados são armazenados em colunas e cada linha dessas colunas guardam os valores de um elemento. Com a linguagem SQL podemos fazer uma junção de linhas de uma tabela com outra tabela.
Com o modelo relacional construirmos tabelas que eliminam dados duplicados, são mais flexíveis na consulta para obter dados especificísticos e fáceis de manter.

Vinculando tabelas usando JOIN

Podemos juntar tabelas durante uma consulta com a declaração JOIN ... ON (Existem outras variações que veremos mais a frente). Usamos essa declaração para vincular uma tabela a outra durante uma consulta. Desse modo usamos valores correspondentes em colunas que especificamos em ambas as tabelas. A sintaxe que vamos usar é essa:

SELECT *
FROM tabela_a JOIN tabela_b
ON tabela_a.coluna_a = tabela_b.coluna_b

Esse exemplo é parecido com a sintaxe básica da declaração SELECT. A diferença é que utilizamos JOIN para fornecer duas tabelas e não somente uma. Depois do ON é onde especificamos as colunas que queremos combinar os valores. O resultado dessa declaração é que realizamos uma consulta nas duas tabelas e retornamos as linhas onde o valor da coluna coluna_a seja igual ao valor da coluna coluna_b.
O uso mais comum da cláusula ON é procurar por colunas com valores iguais, mas também é possível realizar consultas com outras expressões onde o resultado seja verdadeiro ou falso.

Relacionando tabelas com colunas-chave

Vamos imaginar o seguinte cenário: Você é um analista de dados e acabou de ser contratado para analisar os gastos com folha de pagamento por departamento. Você faz o pedido dos dados que vai precisar esperando receber uma tabela parecida com essa:

depart localizacao nome     sobrenome salario
------ ----------- -------- --------- -------
RH     São Paulo   Daniela  Silva     62450
RH     São Paulo   Everton  Oliveira  59300
AD     Fortaleza   Fábio    Feitosa   87654
AD     Fortaleza   Dénis    Reis      87654

Mas não é o que você recebe. Você acaba de receber dois arquivos csv, cada um representando uma tabela. Analisando essas tabelas você percebe que as colunas colaboradores e departamentos se destacam.
Usando o código abaixo vamos criar essas duas tabelas e encontrar o melhor jeito de juntar os dados das tabelas. Se não souber criar uma tabela veja os tutoriais anteriores.

CREATE TABLE departamentos (
	departamento_id BIGINT AUTO_INCREMENT,
	departamento VARCHAR(100),
	cidade VARCHAR(100),
	CONSTRAINT departamento_chave PRIMARY KEY (departamento_id),
	CONSTRAINT depart_cidade_u UNIQUE (departamento, cidade)
);

CREATE TABLE colaboradores (
	colaboradores_id BIGINT AUTO_INCREMENT,
	nome VARCHAR(100),
	sobrenome VARCHAR(100),
	salario INTEGER,
	departamento_id BIGINT REFERENCES departamentos (departamento_id),
	CONSTRAINT colaboradores_chave PRIMARY KEY (colaboradores_id),
	CONSTRAINT colabo_depart_unique UNIQUE (colaboradores_id, departamento_id)
);

INSERT INTO departamentos (departamento, cidade)
VALUES
	('RH', 'São Paulo'),
	('AD', 'Fortaleza');

INSERT INTO colaboradores (nome, sobrenome, salario, departamento_id)
VALUES
	('Erique', 'Silva', 62500, 1),
	('Fabiana', 'Oliveira', 59300, 1),
	('Eveline', 'Reis', 83000, 2),
	('Daniela', 'Ferreira', 95000, 2);

Podemos notar que as duas tabelas que acabamos de criar seguem o modelo proposto por Codd em que cada tabela descreve atributos de uma única entidade, nesse exemplo sobre os colaboradores e os departamentos. Fazendo uma consulta simples vemos que o conteúdo da tabela departamentos é esse:

SELECT * FROM departamentos;
+-----------------+--------------+-----------+
| departamento_id | departamento | cidade    |
+-----------------+--------------+-----------+
|               2 | AD           | Fortaleza |
|               1 | RH           | São Paulo |
+-----------------+--------------+-----------+
2 rows in set (0.003 sec)

A coluna departamento_id é a chave primária da tabela, definimos isso na linha cinco. Isso quer dizer que os valores dessa tabela não podem ser repetidos e não devem ser nulos (deve ser adicionado algum valor). Para não precisarmos adicionar um valor para a coluna departamento_id adicionamos a cláusula AUTO_INCREMENT. Desse modo quando for adicionado uma nova linha a tabela, a coluna departamento_id será acrecida de um valor crescente. Adicionamos a restrição PRIMARY KEY porque cada departamento é único, não existe dois RH numa empresa. Nos próximos tutoriais vamos aprender mais sobre restrições (CONSTRAINT).
Se você realizar uma consulta simples na tabela de colaboradores o conteúdo deve ser esse:

SELECT * FROM colaboradores;
+------------------+----------+-----------+---------+-----------------+
| colaboradores_id | nome     | sobrenome | salario | departamento_id |
+------------------+----------+-----------+---------+-----------------+
|                1 | Erique   | Silva     |   62500 |               1 |
|                2 | Fabiana  | Oliveira  |   59300 |               1 |
|                3 | Eveline  | Reis      |   83000 |               2 |
|                4 | Daniela  | Ferreira  |   95000 |               2 |
+------------------+----------+-----------+---------+-----------------+
8 rows in set (0.003 sec)

A coluna colaboradores_id é utilizada para identificar cada funcionário. Para saber em qual departamento um funcionário trabalha temos a colunas departamento_id. Os valores dessa coluna fazem referência aos valores da coluna departamento_id da tabela departamentos. Essa referência a outra coluna em outra tabela é chamada de chave estrangeira. Uma restrição com chave estrangeira usando referência (REFERENCES) só nos permite adicionar um valor se esse valor já estiver presente na coluna estrangeira, no nosso caso na coluna departamento_id. Isso quer disser que para adicionar o valor 1 na coluna departamento_id da tabela colaboradores esse valor já deve estar presente na coluna departamento_id da tabela departamentos.
Outra restrição é a UNIQUE. Utilizamos UNIQUE para definir que a tabela não pode ter valores repetidos. Agora você deve estar pensando que UNIQUE e PRIMARY KEY são a mesma coisa, mas isso não é verdade. Existem duas diferenças entre as duas. A primeira é que uma tabela só pode ter uma coluna PRIMARY KEY enquanto a mesma tabela pode ter várias colunas UNIQUEs. E a segunda diferença é que uma coluna UNIQUE aceita o valor nulo. Vamos aprender mais sobre essa restrição em outro tutorial.
Nesse momento você deve estar pensando pra que serve essas restrições, além de complicar a sua vida. E a resposta é bem simples: Não permitir a entrada de dados duplicados. Se cada departamento e cidade são únicos porque duplicar esses valores. Se tivéssemos recebidos os dados do jeito que queríamos inicialmente era isso que ia acontecer. Não tem problema ter dados duplicados numa tabela com quatro valores como a nossa, ou quatro mil. Mas agora imagine um banco de dados com milhares de linhas. Agora temos um problema: estamos desperdiçando espaço para armazenar valores duplicados.
Agora que você sabe o básico de como as tabelas podem se relacionar, vamos dar uma olhada em como juntá-los em uma consulta.

Consultando várias tabelas usando JOIN

Quando realizamos uma consulta com JOIN o banco de dados nos retorna uma tabela com as linhas das tabelas lado a lado. Isso para cada linha que a condição passada depois da cláusula ON seja verdadeira. Ainda podemos filtrar os resultados dessa consulta com a cláusula WHERE.
As consultas usando JOIN são parecidas com a sintaxe básica de uma consulta simples com SELECT. A diferença é que usamos JOIN … ON para selecionar as tabelas e as variações de JOIN para definir os critérios da junção.
Vamos começar com um exemplo simples. Para a nossa primeira consulta utilizando JOIN queremos os dados de todas as colunas onde os valores de departamento_id (da tabela colaboradores) e departamento_id (da tabela departamentos) sejam iguais.

SELECT *
FROM colaboradores JOIN departamentos
ON colaboradores.colaboradores_id = departamentos.departamento_id;
+------------------+---------+-----------+---------+-----------------+-----------------+--------------+-----------+
| colaboradores_id | nome    | sobrenome | salario | departamento_id | departamento_id | departamento | cidade    |
+------------------+---------+-----------+---------+-----------------+-----------------+--------------+-----------+
|                2 | Fabiana | Oliveira  |   59300 |               1 |               2 | AD           | Fortaleza |
|                1 | Erique  | Silva     |   62500 |               1 |               1 | RH           | São Paulo |
+------------------+---------+-----------+---------+-----------------+-----------------+--------------+-----------+
2 rows in set (0.002 sec)

Nessa busca foi retornado apenas duas linhas, mesmo fazendo a consulta nas duas tabelas, isso acontece porque definimos uma condição para a busca. E a condição é o valor das colunas colaboradores_id das duas tabelas serem iguais.
É possível fazer uma consulta nas duas colunas sem definir uma condição. Desse modo as tabelas serão apresentadas uma do lado da outra. Para isso use a declaração SELECT * FROM tabela1 JOIN tabela2;.
Utilizando a cláusula ON ou não você vai perceber que a tabela com menos linhas vai se repeti até que as duas tabelas tenham o mesmo número.

JOIN

Utilizamos JOIN ou INNER JOIN quando queremos consultar duas ou mais tabelas que tenham uma tabela em comum. No exemplo anterior, as tabelas colaboradores e departamentos tinham a coluna colaboradores_id em comum. Para os nossos próximos exemplos vamos usar essa tabela:

CREATE TABLE escola_esquerda (id INT, escola_esquerda VARCHAR(50));

CREATE TABLE escola_direita (id INT, escola_direita VARCHAR(50));

INSERT INTO escola_esquerda (id, escola_esquerda)
VALUES
	(1, 'COLEGIO CONTATO MACEIO'),
	(2, 'COLEGIO HARMONIA'),
	(3, 'ESC COLEGIO LATO SENSU'),
	(4, 'COLEGIO OBJETIVO'),
	(5, 'ESC AQUARELA ENSINO E CULTURA');
	
INSERT INTO escola_direita (id, escola_direita)
VALUES
	(1, 'COLEGIO CONTATO MACEIO'),
	(2, 'COLEGIO HARMONIA'),
	(3, 'ESC COLEGIO LATO SENSU'),
	(5, 'ESC AQUARELA ENSINO E CULTURA'),
	(6, 'ESC COLEGIO VITORIA');

Veja um exemplo utilizando JOIN:

SELECT *
FROM escola_esquerda JOIN escola_direita
ON escola_esquerda.id = escola_direita.id;
+------+-------------------------------+------+-------------------------------+
| id   | escola_esquerda               | id   | escola_direita                |
+------+-------------------------------+------+-------------------------------+
|    1 | COLEGIO CONTATO MACEIO        |    1 | COLEGIO CONTATO MACEIO        |
|    2 | COLEGIO HARMONIA              |    2 | COLEGIO HARMONIA              |
|    3 | ESC COLEGIO LATO SENSU        |    3 | ESC COLEGIO LATO SENSU        |
|    5 | ESC AQUARELA ENSINO E CULTURA |    5 | ESC AQUARELA ENSINO E CULTURA |
+------+-------------------------------+------+-------------------------------+
4 rows in set (0.167 sec)

Você deve utilizar o JOIN quando os dados estiverem bem estruturados e uma relação entre as tabelas. Para retornar os valores das duas tabelas use outro tipo de JOIN.

LEFT JOIN e RIGHT JOIN

Utilizamos LEFT JOIN e RIGHT JOIN quando queremos que todos os elementos de uma tabela apareçam na consulta. Por exemplo, você quer que todos os elementos da tabela escola_esquerda apareçam na consulta, assim usamos LEFT JOIN. Os elementos da tabela escola_direita que não tiverem um correspondente na tabela escola_esquerda apareceram em branco (NULL). O mesmo vale para RIGHT JOIN. Veja um exemplo de utilização dos dois JOIN:

SELECT *
FROM escola_esquerda LEFT JOIN escola_direita
ON escola_esquerda.id = escola_direita.id;
+------+-------------------------------+------+-------------------------------+
| id   | escola_esquerda               | id   | escola_direita                |
+------+-------------------------------+------+-------------------------------+
|    1 | COLEGIO CONTATO MACEIO        |    1 | COLEGIO CONTATO MACEIO        |
|    2 | COLEGIO HARMONIA              |    2 | COLEGIO HARMONIA              |
|    3 | ESC COLEGIO LATO SENSU        |    3 | ESC COLEGIO LATO SENSU        |
|    5 | ESC AQUARELA ENSINO E CULTURA |    5 | ESC AQUARELA ENSINO E CULTURA |
|    4 | COLEGIO OBJETIVO              | NULL | NULL                          |
+------+-------------------------------+------+-------------------------------+
5 rows in set (0.004 sec)

SELECT *
FROM escola_esquerda RIGHT JOIN escola_direita
ON escola_esquerda.id = escola_direita.id;
+------+-------------------------------+------+-------------------------------+
| id   | escola_esquerda               | id   | escola_direita                |
+------+-------------------------------+------+-------------------------------+
|    1 | COLEGIO CONTATO MACEIO        |    1 | COLEGIO CONTATO MACEIO        |
|    2 | COLEGIO HARMONIA              |    2 | COLEGIO HARMONIA              |
|    3 | ESC COLEGIO LATO SENSU        |    3 | ESC COLEGIO LATO SENSU        |
|    5 | ESC AQUARELA ENSINO E CULTURA |    5 | ESC AQUARELA ENSINO E CULTURA |
| NULL | NULL                          |    6 | ESC COLEGIO VITORIA           |
+------+-------------------------------+------+-------------------------------+
5 rows in set (0.001 sec)

RIGHT JOIN e LEFT JOIN são usados quando você precisa que todos os elementos de uma tabela apareçam, quando você quer comparar duas tabelas procurando por dados ausentes e quando você precisa saber quais elementos de uma tabela não tem correspondentes na outra tabela.

Usando NULL para encontrar linhas com valores ausentes

Podemos descobrir quais são os valores ausentes numa consulta usando WHERE com NULL. Por exemplo, no exemplo acima a nossa consulta retorna um valor NULL, podemos usar esse valor para descobrir quais são as linhas que não têm correspondentes na outra tabela. Veja como fazer isso:

SELECT *
FROM escola_esquerda LEFT JOIN escola_direita
ON escola_esquerda.id = escola_direita.id
WHERE escola_direita.id IS NULL;
+------+------------------+------+----------------+
| id   | escola_esquerda  | id   | escola_direita |
+------+------------------+------+----------------+
|    4 | COLEGIO OBJETIVO | NULL | NULL           |
+------+------------------+------+----------------+
1 row in set (0.001 sec)

Com esse exemplo descobrimos que o valor 4 da coluna id da tabela escola_esquerda não tem um correspondente na tabela escola_direita.
Obs: Quando for trabalhar com o valor NULL use sempre IS porque NULL = NULL retorna NULL e NULL IS NULL retorna 1.

quinta-feira, 24 de setembro de 2020

Matemática básica e estatística com SQL


Se o seu banco de dados incluir algum tipo de dados do tipo inteiro, decimais ou pontos flutuantes é provável que você vai precisar realizar alguns cálculos com esses dados. Por exemplo, se você precisar saber qual é o valor da soma de todos os elementos de uma coluna, ou você precise adicionar um valor a cada elemento de uma coluna ou linha. Felizmente podemos fazer essas tarefas utilizando a linguagem SQL. Com ela podemos realizar desde operações matemáticas básicas a estatísticas avançadas.
Nesse tutorial, vamos iniciar no básico das operações matemáticas e avançar para as funções matemáticas mais complexas e iniciar em estatística. O dataset que vamos usar pode ser baixado aqui.
Veja abaixo como importar esses dados:

MariaDB [(none)]> create database meu_db;
Query OK, 1 row affected (0.151 sec)

MariaDB [(none)]> use meu_db;
Database changed
MariaDB [meu_db]> create table censu_2015
    -> (CensusTract INT,State VARCHAR(15),County VARCHAR(15),
    -> TotalPop INT,Men INT,Women INT,
    -> Hispanic FLOAT,White FLOAT,Black FLOAT,
    -> Native FLOAT,Asian FLOAT,Pacific FLOAT,
    -> Citizen INT,Income FLOAT,IncomeErr FLOAT,
    -> IncomePerCap FLOAT,IncomePerCapErr FLOAT,Poverty FLOAT,
    -> ChildPoverty FLOAT,Professional FLOAT,Service FLOAT,
    -> Office FLOAT,Construction FLOAT,Production FLOAT,
    -> Drive FLOAT,Carpool FLOAT,Transit FLOAT,
    -> Walk FLOAT,OtherTransp FLOAT,WorkAtHome FLOAT,
    -> MeanCommute FLOAT,Employed INT,PrivateWork FLOAT,
    -> PublicWork FLOAT,SelfEmployed FLOAT,FamilyWork FLOAT,
    -> Unemployment FLOAT);
Query OK, 0 rows affected (0.914 sec)

MariaDB [meu_db]> LOAD DATA LOCAL INFILE
    -> 'C:/Users/user/acs2015_census_tract_data.csv'
    -> INTO TABLE censu_2015
    -> FIELDS TERMINATED BY ','
    -> LINES TERMINATED BY '\n'
    -> IGNORE 1 LINES;
Query OK, 74001 rows affected, 65535 warnings (8.923 sec)
Records: 74001  Deleted: 0  Skipped: 0  Warnings: 97104

Operações matemáticas

Nos primeiros exemplos vamos utilizar as operações básicas que você aprendeu na escola. Na tabela abaixo é mostrado as operações que vamos utilizar com mais frequência.

Operador Operação
+ Adição
- Subtração
* Multiplicação
/ Divisão sem resto
%, MOD(x, y) Modulo ou resto
^ Exponenciação
SQRT(x) Raiz quadrada

Esses operadores podem ser utilizados com números, como numa calculadora, ou com valores em tabelas. Nesse tutorial vamos mostrar os dois.

Tipos de dados e matemática

Quando estiver trabalhando com operações matemáticas é importante saber o tipo de dado onde essas operações serão aplicadas. Não ter conhecimento do tipo de dado pode resultar num erro ou numa operação indesejada.
Aplicando uma operação entre dois números, o resultado retornado segue o padrão abaixo:

  • Dois inteiros retorna um inteiro.
  • Um NUMERIC com outro retorna um NUMERIC.
  • Qualquer operação com um float retorna um float.

Mas com a exponenciação e a raiz quadrada isso não acontece. A operação de raiz quadrada pode retornar um número de ponto flutuante mesmo quando a operação é com um inteiro e a exponenciação pode retornar um inteiro.

Adição, subtração e multiplicação

Até o momento utilizamos a declaração SELECT para recuperar dados de uma tabela. Nesse tutorial vamos utilizá-lo em conjunto com os operadores para realizar operações matemáticas. Vamos começar com as operações de adição, subtração e multiplicação.

MariaDB [(none)]> SELECT 2 + 2;
+-------+
| 2 + 2 |
+-------+
|     4 |
+-------+
1 row in set (0.038 sec)

MariaDB [(none)]> SELECT 9 - 2;
+-------+
| 9 - 2 |
+-------+
|     7 |
+-------+
1 row in set (0.001 sec)

MariaDB [(none)]> SELECT 3 * 4;
+-------+
| 3 * 4 |
+-------+
|    12 |
+-------+
1 row in set (0.007 sec)

Não temos surpresas aqui. Como esperado dois mais dois é quatro, nove menos dois é sete e, como sempre, três vezes quatro é doze. O resultado é mostrado numa coluna, mas não se preocupe, nenhuma tabela está sendo alterada.

Divisão, modulo e raiz quadrada

Na divisão, o resultado sempre será um número de ponto flutuante. Isso porque o operador de divisão faz a divisão exata. Já o operador módulo retorna o resto de uma divisão. Esse operador realiza uma divisão e retorna o resto dessa divisão. Se a divisão for exata o resto é zero, do contrário, o resto será um inteiro. A função de raiz quadrada retorna a raiz quadrada do número passado como parâmetro. Veja um exemplo de utilização:

MariaDB [(none)]> SELECT 9 / 2;
+--------+
| 9 / 2  |
+--------+
| 4.5000 |
+--------+
1 row in set (0.001 sec)

MariaDB [(none)]> SELECT MOD(9,2);
+----------+
| MOD(9,2) |
+----------+
|        1 |
+----------+
1 row in set (0.001 sec)

MariaDB [(none)]> SELECT 9 % 2; -- O mesmo da declaração acima
+-------+
| 9 % 2 |
+-------+
|     1 |
+-------+
1 row in set (0.001 sec)

MariaDB [(none)]> SELECT SQRT(9);
+---------+
| SQRT(9) |
+---------+
|       3 |
+---------+
1 row in set (0.001 sec)

Ordem das operações

Nas expressões matemáticas existe uma ordem em que as operações devem ser feitas. No SQL é a mesma coisa. Por exemplo, qual operação deve ser executada primeiro? A subtração ou a multiplicação? Por isso é importante saber qual operação deve ser aplicada primeiro para atingir o resultado esperado. Essa é a ordem de prioridade dos operadores:

  1. Funções. No caso a função SQRT().
  2. Multiplicação, divisão e módulo.
  3. Adição e subtração.

Seguindo essa ordem as funções serão executadas primeiro, depois a multiplicação, divisão e módulo e, por último, a adição e subtração.
Se em algum momento você precisar a operação de adição ocorra antes da multiplicação, você pode alterar essa ordem de prioridade com parênteses. No exemplo abaixo, o resultado é diferente para cada declaração. Isso porque foi alterada a prioridade das operações.

MariaDB [(none)]> SELECT 5 + 4 * 9;
+-----------+
| 5 + 4 * 9 |
+-----------+
|        41 |
+-----------+
1 row in set (0.003 sec)

MariaDB [(none)]> SELECT (5 + 4) * 9;
+-------------+
| (5 + 4) * 9 |
+-------------+
|          81 |
+-------------+
1 row in set (0.060 sec)

Operações com colunas

Agora que já aprendemos como utilizar os operadores na linguagem SQL vamos aprender a usar esses mesmos operadores com valores em colunas. Quando usamos esses operadores em colunas a operação é realizada em cada linha da tabela.

MariaDB [meu_db]> SELECT State AS 'Estado',
    -> County AS 'Município',
    -> Asian AS 'Asiático',
    -> Hispanic AS 'Hispanico',
    -> Hispanic + Asian AS "Total de Hispânicos e Asiáticos"
    -> FROM censu_2015
    -> WHERE  State = 'Kansas';
+--------+--------------+----------+-----------+---------------------------------+
| Estado | Município    | Asiático | Hispanico | Total de Hispânicos e Asiáticos |
+--------+--------------+----------+-----------+---------------------------------+
| Kansas | Allen        |        0 |         3 |                               3 |
| Kansas | Allen        |      1.5 |         1 |                             2.5 |
| Kansas | Allen        |        0 |       0.1 |             0.10000000149011612 |
| Kansas | Allen        |      1.3 |       6.3 |              7.6000001430511475 |
| Kansas | Allen        |        0 |       5.9 |               5.900000095367432 |
| Kansas | Anderson     |        0 |       0.5 |                             0.5 |
| Kansas | Anderson     |        0 |       0.3 |             0.30000001192092896 |
| Kansas | Wyandotte    |        0 |       7.7 |               7.699999809265137 |
| Kansas | Wyandotte    |        0 |        44 |                              44 |
| Kansas | Wyandotte    |     16.5 |      33.4 |              49.900001525878906 |
| Kansas | Wyandotte    |      2.3 |      28.9 |              31.199999570846558 |
+--------+--------------+----------+-----------+---------------------------------+
770 rows in set (0.130 sec)

Essa não é a saída completa da busca, na sua máquina deve está bem maior. Mas, para o nosso proposito vai servir. Vamos começar explicando o código linha por linha. Na primeira linha selecionamos a coluna “State” e demos um apelido para ela (Estado). Fizemos a mesma coisa na linha dois, três e quatro. Depois pedimos para o gerenciador do banco de dados fazer a soma da coluna Hispanic e Asian e, como nas linhas anteriores, demos um apelido a essa coluna – Lembre-se que cada consulta retorna os dados organizados em colunas. Na linha seis informamos onde esses dados devem ser procurados. E por último fazemos uma filtragem dos dados com WHERE. Com a declaração WHERE estamos dizendo que só queremos os dados das colunas State, County, Asian e Hispanic onde o valor da coluna State seja igual a Kansas.
Com esse exemplo fica fácil perceber como as operações funcionam em tabelas. Como exercício tente realizar as outras operações e mudar o estado.

Porcentagem

Para o nosso próximo exemplo vamos descobrir qual é a porcentagem de homens no estado do Texas. Para isso vamos precisar saber a quantidade total da população e a quantidade total de homens. Nosso banco de dados já tem essas informações.
Veja como descobrir a porcentagem de homens no estado do Texas no exemplo abaixo:

MariaDB [meu_db]> SELECT State AS 'Estado',
    -> SUM(Men) AS 'Total Homens',
    -> SUM(Women) AS 'Total Mulheres',
    -> (SUM(Men) * 100) / (SUM(Men) + SUM(Women)) AS 'Porcentagem de Homens'
    -> FROM censu_2015
    -> WHERE State = 'Texas';
+--------+--------------+----------------+-----------------------+
| Estado | Total Homens | Total Mulheres | Porcentagem de Homens |
+--------+--------------+----------------+-----------------------+
| Texas  |     13171316 |       13367298 |               49.6308 |
+--------+--------------+----------------+-----------------------+
1 row in set (0.316 sec)

Nesse exemplo usamos a função SUM() para somar todos as linhas das colunas Men e Women, lembre-se que estamos somando apenas os valores das linhas que tenham o valor Texas na coluna State. Depois utilizamos as operações de multiplicação, divisão e soma para descobrir a porcentagem de homens no estado do Texas (Regra de três).

Função de soma e médias

As duas funções mais utilizadas na análise de dados são a SUM() e AVG(). Isso porque a função SUM() faz a soma de todas as linhas de uma coluna, como vimos no exemplo anterior. E a função AVG() retorna o valor médio de uma coluna numérica. O que a função AVG() faz é somar todos os valores de uma coluna e depois dividir pelo número de linhas. Veja um exemplo de utilização das duas funções abaixo:

MariaDB [meu_db]> SELECT AVG(TotalPop) FROM censu_2015;
+---------------+
| AVG(TotalPop) |
+---------------+
|     4325.5915 |
+---------------+
1 row in set (1.760 sec)

MariaDB [meu_db]> SELECT SUM(TotalPop) FROM censu_2015;
+---------------+
| SUM(TotalPop) |
+---------------+
|     320098094 |
+---------------+
1 row in set (0.168 sec)

Com a função AVG() descobrimos que a média dos valores da coluna TotalPop é 4325.5915 e com a função SUM() descobrimos que o total da soma da coluna TotalPop é 320098094.

terça-feira, 18 de agosto de 2020

Importando e exportando dados com SQL

Photo by Ken Yam on Unsplash

Até o momento aprendemos a criar um banco de dados, criar uma tabela e inserir dados nessa tabela com a declaração INSERT. O modo que vinhamos fazendo, inserindo linha a linha na tabela, pode ser útil para tabelas de testes rápidos ou adicionar novas linhas numa tabela já existente, mas o mais comum é inserir centenas ou até mesmo milhares de linhas. E fazer isso do jeito que vinhamos fazendo não é viável. Mas não se preocupe, existem outros meios.
Se os seus dados estiverem num arquivo com uma estrutura definida, separado em colunas, como os arquivos CSV, você pode importar esses dados diretamente para uma tabela com a instrução LOAD DATA INFILE. Essa instrução é utilizada para importar dados em massa.
Também podemos utilizar a instrução SELECT INTO OUFILE para exportar os dados de uma tabela. Essa instrução é muito útil quando você quer compartilhar os dados com um colega ou exportar os dados para outro formato, como um arquivo do Excel.
Nesse tutorial vamos aprender como importar e exportar dados utilizando a linguagem SQL. Mas antes de começarmos vamos verificar se a importação de dados é permitida com a instrução SHOW VARIABLES LIKE '%infile%'; e verificar onde o arquivo que vamos importar deve estar, com a instrução SHOW VARIABLES LIKE 'secure_file_priv';.

mysql> SHOW VARIABLES LIKE '%infile%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| local_infile  | ON    |
+---------------+-------+
1 row in set (0.01 sec)

mysql> SHOW VARIABLES LIKE 'secure_file_priv';
+------------------+------------------------------------------------+
| Variable_name    | Value                                          |
+------------------+------------------------------------------------+
| secure_file_priv | C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\ |
+------------------+------------------------------------------------+
1 row in set (0.01 sec)

Com essas duas instruções, descobrimos que a importação de arquivos é permitida e a pasta onde devemos colocar o arquivo que vamos importar é a Uploads. Se o valor da variável local_infile for OFF mude o seu valor com a instrução SET GLOBAL local_infile=1;.

Importando dados de um arquivo CSV com SQL

Os arquivos CSV são arquivos de texto puro. Nesses arquivos não existe formatação, os dados, nesse tipo de arquivo, são delimitados por vírgula. Você não precisa de um arquivo com extensão csv, pode ser um simples arquivo txt, mas os dados precisam estar delimitados por vírgulas. Esse é o conteúdo do arquivo que vamos utilizar:

Nome, Idade, Endereco
Amelia, 23, Rua Antonio Monteiro
Rafael, 52, 25 de Marco
Daniel, 32, Teotonio alcantara

Para importar esses dados vamos precisar criar uma tabela com três colunas. Veja o exemplo abaixo:

mysql> CREATE TABLE cadastro
    -> (nome VARCHAR(10), idade SMALLINT, endereco VARCHAR(25));
Query OK, 0 rows affected (0.76 sec)

mysql> LOAD DATA INFILE
    -> 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/dados.txt'
    -> INTO TABLE cadastro
    -> FIELDS TERMINATED BY ','
    -> LINES TERMINATED BY '\n'
    -> IGNORE 1 LINES;
Query OK, 3 rows affected (0.16 sec)
Records: 3  Deleted: 0  Skipped: 0  Warnings: 0

mysql> SELECT * FROM cadastro;
+--------+-------+------------------------+
| nome   | idade | endereco               |
+--------+-------+------------------------+
| Amelia |    23 |  Rua Antonio Monteiro  |
| Rafael |    52 |  25 de Marco           |
| Daniel |    32 |  Teotonio alcantara    |
+--------+-------+------------------------+
3 rows in set (0.02 sec)

Como funciona a instrução LOAD DATA INFILE

Na primeira instrução criamos uma tabela com três colunas. Cada uma para guardar strings, números e strings, respectivamente. Repare que esses são os tipos de dados do nosso arquivo dados.txt.
Na primeira linha da segunda instrução, estamos informando que vamos importar um arquivo. Na segunda linha, passamos o caminho desse arquivo entre aspas simples (Repare que não usamos barras invertidas). Depois definimos que os dados estão delimitados por vírgula, a linha termina com uma quebra de linha e que na leitura desse arquivo deve ser ignorado uma linha – a primeira.
Ignoramos uma linha porque, geralmente, a primeira linha dos arquivos csv contêm os nomes das colunas e não os dados.

Exportando uma tabela para um arquivo CSV

Você pode exportar tabelas de um banco de dados para um arquivo CSV com a instrução INTO OUTFILE. Com essa instrução você pode exportar os dados de uma tabela delimitando os valores com qualquer carácter especifico. Veja um exemplo:

mysql> SELECT nome, idade, endereco
    -> INTO OUTFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/dados.csv'
    -> FIELDS TERMINATED BY ','
    -> LINES TERMINATED BY '\n'
    -> FROM cadastro;
Query OK, 3 rows affected (0.03 sec)

Como funciona a instrução INTO OUTFILE

Na primeira linha, utilizamos SELECT para selecionar as colunas que queremos exportar. Na segunda linha definimos o caminho do arquivo. Depois definimos que os dados serão delimitados por vírgula, as linhas vão terminar com quebra de linha e, por último, informamos de qual tabela vamos exportar os dados.

domingo, 16 de agosto de 2020

Entendendo tipos de dados do SQL

Photo by travelnow.or.crylater on Unsplash

Quando se procura um banco de dados é bom verificar os tipos de dados em cada em cada tabela e coluna. As vezes o criador do banco de dados disponibiliza um dicionário dos dados. O dicionário é um arquivo que explica os dados do bancos de dados, como os dados foram obtidos, a relação entre eles, a disposição dos dados, e mais. Infelizmente, encontrar um banco de dados com a documentação é muito difícil. Então, o jeito é aprender sobre o banco de dados fazendo inspeções das tabelas e seus dados.
Entender os tipos de dados é uma tarefa importante na analise e criação de bancos de dados. Com os dados armazenados de forma correta a analise e a criação do banco de dados se torna mais precisa. Entender o conceito de tipos de dados pode ser útil além da linguagem SQL, esse é um conceito que pode ser útil em outras linguagens. Os conhecimentos aprendidos nesse tutorial não se aplica apenas a linguagem SQL.
As colunas dos bancos de dados SQL, só podem armazenar um tipo de dado por coluna. Não é possível armazenar dois tipo de de dados na mesma coluna. Quando o tipo de dado é definido com a declaração CREATE TABLE, esse é o único tipo de dado permitido na coluna. A definição do tipo é especifica logo após o nome da coluna. Veja um exemplo:

MariaDB [meu_BD]> CREATE TABLE jogos_brasil(
    -> data_jogo DATE,
    -> gols INTEGER
    -> );

Na tabela jogos_brasil, criamos a coluna data_jogo e definimos que essa coluna vai guardar dados do tipo data adicionando DATE depois do seu nome. Fizemos a mesma coisa com a tabela gols, a diferença é o tipo de dados que essa tabela vai guardar, que é dados do tipo INTEGER (inteiro).
Esses são os tipos de dados mais comuns nos bancos de dados:

  • Caracteres: Qualquer carácter ou simbolo
  • Números: Incluí todos os números
  • Data e hora: Informações de dados e horas

Nesse tutorial vamos aprender a utilizar esses tipos de dados a fundo.

Caracteres

As sequências de caracteres são o tipo de dados mais comum. Isso porque esse tipo pode ser utilizado para guardar dados um conjunto de números, texto ou datas. Mas o dado continua sendo do tipo carácter, '1' e 1 são tipos de dados diferentes. O dado que pode ser guardado no tipo carácter é o '1'. Esses são os tipos de caracteres:

  • CHAR(n) Esse tipo de dado tem um comprimento máximo definido com n. Criando uma coluna com CHAR(25), o tamanho máximo de caracteres que podem ser guardados em cada linha é de vinte caracteres. Se for armazenado menos caracteres o restante será preenchido com espaços em branco. Esse tipo também pode ser escrito na forma longa, CHARACTER(n). A forma mais comum é a curta.
  • VARCHAR(n): Esse tipo de dado é parecido com o anterior, a diferença é que se definirmos o tamanho máximo de 25 caracteres, mas só adicionamos dez caracteres, o restante não será preenchido. Esse tipo de dados é mais utilizado em grandes bancos de dados, porque esse tipo de dado economiza espaço. A sua forma longa é VARYING(n).
  • TEXT: Com esse tipo de dado você pode guardar dados de comprimento ilimitado (A sequência mais longa pode ter o tamanho de até 1GB).

Não a uma diferença de desempenho entre os três tipos de dados. A economia de espaço utilizando os tipos de dados VARCHAR() e TEXT pode ser uma vantagem, mas só em questão de armazenamento. Já que esses tipos de dados vão alocar apenas o espaço necessário.

Números

As colunas do tipo numérico, além de poder guardar dados desse tipo, nos permitem realizar operações matemáticas com esses dados como a soma, multiplicação, divisão entre outros. E nos permite ordenar os dados de forma crescente ou decrescente. Essa é uma vantagem, se a ordem é importante no seu projeto. Por isso, se no seu projeto vai ser preciso fazer operações matemáticas ou precisar de uma ordem, utilize os tipos de dados numéricos.
Esses são os tipos numéricos da linguagem SQL:

  • Inteiros: números inteiros, positivos e negativos
  • Ponto fixo e ponto flutuante: dois formatos de frações de números inteiros

Inteiros

Os dados mais comum nos bancos de dados são os do tipo inteiro. Isso porque os números inteiros estão em toda parte. Olhe ao seu redor e veja quantas coisas podem ser contadas ou medidas com números inteiros.
Existem três tipos de dados do tipo inteiro: smallint, integer e bigint. A diferença entre esses três tipos é o valor máximo que cada tipo pode guardar. Na tabela abaixo, é mostrado a quantidade que cada tipo pode armazenar e a quantidade de memoria utilizada no armazenamento:

Tipo de dado Tamanho em bytes Intervalo
smallint 2 bytes −32768 a +32767
integer 4 bytes −2147483648 a +2147483647
bigint 8 bytes −9223372036854775808 a +9223372036854775807

Uma preocupação ao definir o tipo de dados é o seu consumo de memoria e a escalonabilidade dos dados. Se você escolher um tipo que consome pouca memória e depois esse tipo não conseguir armazenar os seus dados, você terá um problema. Do outro lado é possível que você escolha um tipo que consome mais memoria e nunca venha a precisar dessa precisão extra. Por isso faça um estudo pra definir qual tipo usar.

Tipos de ponto flutuante

Existem dois tipos de de dados de ponto flutuante, real e de precisão dupla. a diferença entre os dois é a quantidade de dados que eles podem representar. O tipo real tem precisão de seis casas decimais e o de precisão dupla quinze. Veja uma lista dos tipos de ponto flutuante:

Tipo de dado Tamanho em bytes Intervalo
numeric, decimal Variável Até 131072 dígitos antes da vírgula decimal;
Até 16383 dígitos após o ponto decimal
real 4 bytes Precisão de até 6 casas decimais
double precision 8 bytes Precisão de até 15 casas decimais

Veja um exemplo de como utilizar cada tipo de ponto flutuante:

MariaDB [meu_BD]> CREATE TABLE tipos_numericos(
    -> coluna_numeric NUMERIC(20, 5),
    -> coluna_real REAL,
    -> coluna_d_precisao DOUBLE PRECISION
    -> );
Query OK, 0 rows affected (0.021 sec)

MariaDB [meu_BD]> INSERT INTO tipos_numericos
    -> VALUES
    -> (.8, .8, .8),
    -> (3.13579, 3.13579, 3.13579),
    -> (2.1234469287, 2.1234469287, 2.1234469287);
Query OK, 3 rows affected, 1 warning (0.006 sec)
Records: 3  Duplicates: 0  Warnings: 1

MariaDB [meu_BD]> SELECT * FROM tipos_numericos;
+----------------+--------------+-------------------+
| coluna_numeric | coluna_real  | coluna_d_precisao |
+----------------+--------------+-------------------+
|        0.80000 |          0.8 |               0.8 |
|        3.13579 |      3.13579 |           3.13579 |
|        2.12345 | 2.1234469287 |      2.1234469287 |
+----------------+--------------+-------------------+
3 rows in set (0.001 sec)

Note que os dois último números da coluna coluna_numeric foram arredondados e o primeiro foi preenchido com zeros. Isso acontece porque definimos a precisão de cinco casas decimais. Assim, se o número não tiver precisão suficiente as casas decimais serão preenchidas com zeros. E se passar do número especificado, o número é arredondado.

Escolhendo o tipo de dados numérico

Definir qual tipo de dados usar é uma tarefa que demanda estudo e depende de cada caso, mas existem alguma dicas que podem ser útil na escolha:

  1. Sempre que possível utilize números inteiros. Só use tipos de ponto flutuante se for necessário.
  2. Se precisar utilizar dados de ponto flutuante e precisar de exatidão no cálculos utilize o NUMERIC ou se equivalente DECIMAL.
  3. Escolha um tipo de dado grande o suficiente. Só use um tipo de dado menor quando você tiver certeza que não vai precisar de um número maior.

Data e hora

Quando você digita uma data em um formulário de pesquisa, você está obtendo os benefícios dos bancos de dados terem conhecimento da hora atual, além da capacidade de suportar os formatos de datas, horas e as variedades do calendário, como os anos bissextos e fusos horários. Isso é crucial para narrar histórias com dados, porque a questão de quando algo ocorreu normalmente é uma questão tão importante quanto quem, o quê ou quantos estavam participando da historia.
Veja uma lista dos tipos de dados de data e hora mais usados:

Tipo de dado Tamanho em bytes Descrição Intervalo
timestamp 8 bytes Data e hora 4713 AC to 294276 DC
date 4 bytes Data 4713 AC to 5874897 DC
time 8 bytes Hora 00:00:00 to 24:00:00

Veja um exemplo de como utilizar esses tipos de dados:

MariaDB [meu_BD]> CREATE TABLE data_hora(
    -> coluna_timestamp TIMESTAMP,
    -> coluna_data DATE,
    -> coluna_time TIME
    -> );
Query OK, 0 rows affected (0.021 sec)

MariaDB [meu_BD]> INSERT INTO data_hora
    -> VALUES
    -> ('2018-12-31 01:00', '2018-04-23', '12:00:21'),
    -> ('2012-06-29 02:00', '2019-04-23', '14:30:22'),
    -> (now(), '2018-04-23', '12:00:21');

Query OK, 3 rows affected (0.003 sec)

A função now() retorna a data e hora de quando a função é chamada. Se for passado uma data errada isso vai gerar um erro. Um exemplo de data errada é: '2018-02-30'.

sábado, 15 de agosto de 2020

Exploração de dados com SELECT

Photo by Edu Grande on Unsplash

A melhor parte de analisar os dados é quando vou entrevistar os dados (obter informações). É nessa etapa que descobrimos se os dados estão completos, se existe algum dado que não é necessário e, acima de tudo, que tipo de informações podemos obter com esses dados. Uma maneira de pensar nessa etapa é como se ela você uma entrevista de emprego. Você deve fazer perguntas que vão lhe dar as informações para contratar essa pessoa e onde ela será mais produtiva. Do mesmo modo você deve fazer com os dados: Esses dados me serão útil? Onde?
A entrevista é importante porque você obtém informações. Por exemplo, numa entrevista de emprego você descobre que metade dos entrevistados não colocou o nome do pai ou não informou um endereço de e-mail. Na entrevista você pode descobrir se os seus dados estão incorretos: nomes trocados, faltando letras, data no formato errado, entre outras coisas. Esse tipo de informação se torna parte dos dados.
Na linguagem SQL, começamos a entrevista com a declaração SELECT. Essa declaração é utilizada para recuperar informações de linhas e colunas nos bancos de dados. A instrução SELECT pode ser simples, retornando toda a informação sem nenhum filtro, ou pode ser complexa, retornando dezenas de tabelas e aplicando filtros e cálculos.
Nesse tutorial vamos começar com instruções SELECT simples.

Sintaxe básica da declaração SELECT

Nesse exemplo, vamos selecionar todas as linhas e colunas da tabela funcionarios. Essa coluna está no banco de dados que criamos no último tutorial. É importante ter um banco de dados selecionado antes de clamar a instrução SELECT. Você pode notar o banco de dados selecionado entre colchetes.

MariaDB [(none)]> USE meu_banco_de_dados;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [meu_banco_de_dados]> SELECT * FROM funcionarios;
+------+---------+----------+-------------------+-------------+---------+
| id   | p_nome  | u_nome   | profissao         | data_inicio | salario |
+------+---------+----------+-------------------+-------------+---------+
|    0 | Eveline | Ferreira | Vendedor          | 2018-02-03  |    3400 |
|    1 | Osvaldo | Perreira | Vendedor          | 2018-03-03  |    3400 |
|    2 | Maria   | Saturno  | Gerente de vendas | 2018-01-01  |    8500 |
|    3 | Mariana | Reis     | Diretor           | 2018-01-01  |    5000 |
|    4 | Marisa  | Lima     | Gerente           | 2019-03-01  |    9000 |
+------+---------+----------+-------------------+-------------+---------+
5 rows in set (0.001 sec)

Esse exemplo mostra a forma mais básica de selecionar dados com a linguagem SQL. Utilizamos o asterisco, depois da declaração SELECT, como um curinga. O curinga é utilizado no lugar de um valor especifico. O asterisco assume o valor de todos os valores possíveis. A instrução utilizada nesse exemplo é uma forma de dizer: 'selecione todas as colunas da tabela funcionarios'. Se você passar o nome de uma coluna, no lugar do asterisco, apenas os valores dessa coluna serão apresentados. A declaração FROM indica onde a declaração SELECT deve procurar os dados. O ponto e vírgula é utilizado para sinalizar o fim da instrução.

Consultando um conjunto de colunas

O asterisco é utilizado para descobrir todo o conteúdo de uma tabela. Com grandes bancos de dados é mais prático limitar o número de coluna que a declaração deve retornar. Você pode não ter interesse nos dados sobre id ou data de entrada, você pode estar procurando informações sobre profissão e salário. Podemos definir os dados que temos interesse passando os nomes das colunas separados por vírgula depois da declaração SELECT. Veja um exemplo:

MariaDB [meu_banco_de_dados]> SELECT salario, profissao, p_nome FROM funcionarios;
+---------+-------------------+---------+
| salario | profissao         | p_nome  |
+---------+-------------------+---------+
|    3400 | Vendedor          | Eveline |
|    3400 | Vendedor          | Osvaldo |
|    8500 | Gerente de vendas | Maria   |
|    5000 | Diretor           | Mariana |
|    9000 | Gerente           | Marisa  |
+---------+-------------------+---------+
5 rows in set (0.001 sec)

Note que os dados foram retornados na ordem em que passamos os nomes das colunas. Primeiro o salário, depois a profissão e por último o nome.
Mesmos esses exemplos básicos, mostram uma boa estrategia para iniciar a analise de dados. É uma prática comum verificar se todos os dados estão presentes e no formato certo. As datas estão completas? Dia, mês e ano? Ou só o mês e o ano? Existem nomes começando, misteriosamente, com a letra C? Esses são alguns problemas que você pode achar nessa "entrevista".
Nesse exemplo, utilizamos um banco de dados com poucas linhas, mas quando você se deparar com um banco de dados, com centenas ou milhares de linhas, é preciso fazer uma analise rápida da quantidade e qualidade dos dados. Vamos fazer isso com mais algumas declarações do SQL.

Selecionando valores únicos com a declaração DISTINCT

É muito comum encontrar colunas com valores duplicados. Na coluna profissao temos algumas linhas com o valor vendedor. Isso porque uma empresa pode ter vários vendedores. Se você precisar saber quais profissões estão presentes na tabela profissao, podemos fazer uma consulta que vai retornar apenas valores únicos, eliminando os valores duplicados com a declaração DISTINCT (os valores não serão mostrados, mais continuam na tabela).

MariaDB [meu_banco_de_dados]> SELECT DISTINCT profissao
    -> FROM funcionarios;
+-------------------+
| profissao         |
+-------------------+
| Vendedor          |
| Gerente de vendas |
| Diretor           |
| Gerente           |
+-------------------+
4 rows in set (0.001 sec)

Mesmo a tabela funcionarios tendo cinco linhas, essa instrução nos mostro apenas quatro. Isso porque o valor Vendedor aparece mais de uma vez e a declaração DISTINCT nos mostra apenas valores únicos. Essa declaração é útil para analisar a quantidade e a qualidade dos dados. Com ela podemos saber o quanto de dados vamos analisar e quantos desses dados estão numa boa qualidade. Por exemplo, com a declaração DISTINCT podemos saber se existem dados escrito de forma de forma errada, como o valor Vendedor escrito dessa forma: Cendedor.
Podemos ver os valores únicos de mais de uma coluna por vez. Para isso precisamos passar os nomes das colunas separadas por vírgula.

MariaDB [meu_banco_de_dados]> SELECT DISTINCT profissao, salario
    -> FROM funcionarios;
+-------------------+---------+
| profissao         | salario |
+-------------------+---------+
| Vendedor          |    3400 |
| Gerente de vendas |    8500 |
| Diretor           |    5000 |
| Gerente           |    9000 |
+-------------------+---------+
4 rows in set (0.001 sec)

Desse modo podemos saber, por exemplo, quantos profissões tem salários diferentes. Se tiver uma pessoa que tem a mesma profissão, mas que recebe um salário diferente, será retornado o valor profissão para cada salário diferente.
Adicione uma nova linha na tabela funcionarios com o valor Vendedor e com um salário diferente de 3400 (Veja como fazer isso no tutorial anterior). Depois chame a mesma instrução do exemplo acima, o resultado deve ser parecido com esse:

MariaDB [meu_banco_de_dados]> SELECT DISTINCT profissao, salario
    -> from funcionarios;
+-------------------+---------+
| profissao         | salario |
+-------------------+---------+
| Vendedor          |    3400 |
| Gerente de vendas |    8500 |
| Diretor           |    5000 |
| Gerente           |    9000 |
| Vendedor          |    6500 |
+-------------------+---------+
5 rows in set (0.001 sec)

Note que agora temos dois valores Vendedor na coluna profissão, mas com os valores da coluna salário diferentes.

Ordenando dados com a declaração ORDER BY

Um maneira de encontrar algum sentido nos dados é organizando esses dados de alguma forma. Quando os dados estão organizados fica mais fácil encontrar algum padrão que não percebemos quando os dados estão misturados. Com a linguagem SQL podemos organizar os dados de uma consulta com a declaração ORDER BY seguido do nome da coluna ou das colunas.
Quando utilizamos ORDER BY numa consulta não estamos modificando a tabela, apenas os dados retornados pela consulta. Veja um exemplo de como utilizar ORDER BY:

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> ORDER BY salario DESC;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Marisa  | Gerente           |    9000 |
| Maria   | Gerente de vendas |    8500 |
| Fabiana | Vendedor          |    6500 |
| Mariana | Diretor           |    5000 |
| Eveline | Vendedor          |    3400 |
| Osvaldo | Vendedor          |    3400 |
+---------+-------------------+---------+
6 rows in set (0.001 sec)

Nesse exemplo, organizamos os dados de forma decrescente adicionando a palavra-chave DESC. Por padrão ORDER BY organiza os dados de forma crescente. Ordenando os valores de forma decrescente descobrimos qual é a profissão que ganha mais.
A organização nos permite fazer consultas de forma mais direta e uma maior flexibilização na hora de visualizar os dados. Um dessas flexibilidades é a capacidade de organizar mais de uma coluna.

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, data_inicio
    -> FROM funcionarios
    -> ORDER BY p_nome ASC, data_inicio DESC;
+---------+-------------------+-------------+
| p_nome  | profissao         | data_inicio |
+---------+-------------------+-------------+
| Eveline | Vendedor          | 2018-02-03  |
| Fabiana | Vendedor          | 2019-03-20  |
| Maria   | Gerente de vendas | 2018-01-01  |
| Mariana | Diretor           | 2018-01-01  |
| Marisa  | Gerente           | 2019-03-01  |
| Osvaldo | Vendedor          | 2018-03-03  |
+---------+-------------------+-------------+
6 rows in set (0.001 sec)

Nesse exemplo, organizamos a coluna p_nome de forma crescente (ordem alfabética) e, a coluna data_inicio, de forma decrescente. Mas se a coluna data_inicio esta organizada de forma decrescente porque a data 2019-03-20 não está no topo? Porque a prioridade é a coluna p_nome. Primeiro os resultados são organizados por nomes e depois por data, criando subgrupos de organização.
Com esse exemplo, podemos obter a resposta para o tipo de pergunta: “Qual é a pessoa, que o nome começa com F, que está na empresa a mais tempo?”. Esse é um exemplo bobo, mas com os dados certos essa informação é muito importante.

Filtrando linhas com WHERE

Com um banco de dados grande você vai precisar limitar os resultados de uma consulta. Talvez você queira apenas os resultados que satisfaça algumas condições. Por exemplo, as profissões que ganham mais de três mil ou o nome das pessoas que trabalham como vendedor. Para limitar os resultados com condições que os dados devem ter usamos a declaração WHERE.
A declaração WHERE é utilizada para encontrar dados que correspondam a um valor especifico ou satisfação uma condição. Utilizando WHERE você pode excluir linhas com base em condições.
A declaração WHERE vem depois da declaração FROM e do nome da tabela onde vamos fazer uma consulta. Veja um exemplo:

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE profissao = 'Vendedor';
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Eveline | Vendedor  |    3400 |
| Osvaldo | Vendedor  |    3400 |
| Fabiana | Vendedor  |    6500 |
+---------+-----------+---------+
3 rows in set (0.003 sec)

Nesse exemplo, fizemos uma consulta nas colunas p_nome, profissao e salario da tabela funcionarios e definimos que queremos ver apenas as linhas onde o valor da coluna profissao é igual a Vendedor. No exemplo acima, utilizamos apenas o operador igual, mas a linguagem SQL tem suporte a outros operadores. Veja a lista dos operadores suportados pela linguagem SQL:

Operador Função Exemplo
= Igual WHERE profissao = ‘Vendedor’
<> Diferente WHERE profissao <> ‘Vendedor’
> Maior que WHERE salario > 3000
< Menor que WHERE salario < 6000
>= Maior ou igual WHERE salario >= 6500
<= Menor ou igual WHERE salario <= 6500
BETWEEN Entre x e y WHERE salario BETWEEN 6000 AND 9000
IN Corresponde a um dos elementos passados WHERE profissao IN (‘Vendedor’, 'Gerente de vendas')
LIKE Corresponde a um padrão (Case sensitive) WHERE p_nome LIKE ‘Mar%’
NOT Nega uma condição WHERE p_nome NOT ILIKE ‘mar%’

Agora que já sabemos quais operadores podemos usar, vamos utilizar cada operador num exemplo. Vamos começar com o operador igual. Vamos selecionar todas as linhas com o valor da coluna salario igual a 3400.

MariaDB [meu_banco_de_dados]> SELECT u_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE salario = 3400;
+----------+-----------+---------+
| u_nome   | profissao | salario |
+----------+-----------+---------+
| Ferreira | Vendedor  |    3400 |
| Perreira | Vendedor  |    3400 |
+----------+-----------+---------+
2 rows in set (0.001 sec)

Para o nosso próximo exemplo, vamos selecionar todas as linhas que tenham um valor diferente de Vendedor na coluna profissao.

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE profissao <> 'Vendedor';
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Marisa  | Gerente           |    9000 |
+---------+-------------------+---------+
3 rows in set (0.001 sec)

No exemplo abaixo, vamos usar os operadores >, <, >=, <=.

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE salario > 4000;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Marisa  | Gerente           |    9000 |
| Fabiana | Vendedor          |    6500 |
+---------+-------------------+---------+
4 rows in set (0.001 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE salario < 7000;
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Eveline | Vendedor  |    3400 |
| Osvaldo | Vendedor  |    3400 |
| Mariana | Diretor   |    5000 |
| Fabiana | Vendedor  |    6500 |
+---------+-----------+---------+
4 rows in set (0.001 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE salario >= 3400;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Eveline | Vendedor          |    3400 |
| Osvaldo | Vendedor          |    3400 |
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Marisa  | Gerente           |    9000 |
| Fabiana | Vendedor          |    6500 |
+---------+-------------------+---------+
6 rows in set (0.001 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE salario <= 9000;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Eveline | Vendedor          |    3400 |
| Osvaldo | Vendedor          |    3400 |
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Marisa  | Gerente           |    9000 |
| Fabiana | Vendedor          |    6500 |
+---------+-------------------+---------+
6 rows in set (0.001 sec)

Para o nosso próximo exemplo vamos selecionar todas as linhas que o valor da coluna salario esteja entre 3500 e 8900.

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE salario BETWEEN 3500 AND 8900;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Fabiana | Vendedor          |    6500 |
+---------+-------------------+---------+
3 rows in set (0.004 sec)

Com operador IN você pode passar um conjunto de valores para a declaração WHERE. Desse modo a declaração WHERE vai fazer mais de uma verificação por dado. Por exemplo, você pode querer selecionar as linhas que tenham os valores 'Vendedor' ou 'Gerente' na coluna profissao. Veja o exemplo disso:

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE profissao IN ('Gerente', 'Vendedor');
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Eveline | Vendedor  |    3400 |
| Osvaldo | Vendedor  |    3400 |
| Marisa  | Gerente   |    9000 |
| Fabiana | Vendedor  |    6500 |
+---------+-----------+---------+
4 rows in set (0.001 sec)

Usando o operador LIKE

Para o nosso próximo exemplo vamos utilizar o operador LIKE. Esse operador vai selecionar dados que começam com a string que passamos para o operador. É importante notar que o operador LIKE diferencia letras maiúsculas de minusculas, então Mar e mar são diferentes.

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE p_nome LIKE 'Mar%';
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Marisa  | Gerente           |    9000 |
+---------+-------------------+---------+
3 rows in set (0.001 sec)

O sinal de porcentagem (%) no final da string é utilizado para sinalizar que queremos qualquer valor que comece com 'Mar' não importa o tamanho que esse valor tenha. Esse caractere também pode ser utilizado para selecionar valores com um final de string em comum. Por exemplo, na coluna p_nome existem dois nomes que terminam com ‘ana’ no final, Fabiana e Mariana. Para selecionar as linhas que tenham esses valores passaríamos a string ‘%ana’ para o operador LIKE.
Outro carácter utilizado é o underline (_). Esse caractere é usado para sinalizar que queremos os valores com apenas um carácter a mais dos que já passamos. Por exemplo, passando ‘Marian_’ para o operador LIKE, o operador vai retornar todos os valores que comecem com ‘Marian’ e tenham um carácter a mais. Esse carácter pode ser qualquer um, pode ser um a, um b ou c. Se começar com ‘Marian’ e tiver somente mais um carácter o valor será selecionado pelo operador. E o underline pode ser usado no meio da palavra.
Veja outros exemplos de utilização dos caracteres de porcentagem e underline:

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE p_nome LIKE '%ana';
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Mariana | Diretor   |    5000 |
| Fabiana | Vendedor  |    6500 |
+---------+-----------+---------+
2 rows in set (0.000 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE p_nome LIKE '%ia%';
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Fabiana | Vendedor          |    6500 |
+---------+-------------------+---------+
3 rows in set (0.001 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE p_nome LIKE 'Marian_';
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Mariana | Diretor   |    5000 |
+---------+-----------+---------+
1 row in set (0.001 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE p_nome LIKE 'Mar_ana';
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Mariana | Diretor   |    5000 |
+---------+-----------+---------+
1 row in set (0.001 sec)

Combinando operadores com AND ou OR

A linguagem SQL nos permite utilizar mais de um operador ao mesmo tempo. Assim podemos definir mais de uma condição para selecionar um valor. Por exemplo, você pode querer selecionar apenas os valores que tenham o valor 'Vendedor' na coluna profissao e o valor da coluna salario maior que 3400. Para isso usamos a palavra chave AND. Com ela o dado só será selecionado se atender as duas condições, ter o valor ‘Vendedor’ na coluna profissao E (AND) o valor da coluna salario maior que 3400.
A palavra-chave OR define duas condições e se qualquer uma dessas condições for satisfeita o dado é selecionado. Por exemplo, se você quiser selecionar os dados que tenham o valor ‘Vendedor’ na coluna profissao ou o valor da coluna salario seja maior que 3000, você deve usar OR.
Veja exemplos de como utilizar AND e OR:

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE profissao = 'Vendedor'
    -> AND salario > 3400;
+---------+-----------+---------+
| p_nome  | profissao | salario |
+---------+-----------+---------+
| Fabiana | Vendedor  |    6500 |
+---------+-----------+---------+
1 row in set (0.001 sec)

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE profissao = 'Vendedor'
    -> OR salario > 3000;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Eveline | Vendedor          |    3400 |
| Osvaldo | Vendedor          |    3400 |
| Maria   | Gerente de vendas |    8500 |
| Mariana | Diretor           |    5000 |
| Marisa  | Gerente           |    9000 |
| Fabiana | Vendedor          |    6500 |
+---------+-------------------+---------+
6 rows in set (0.001 sec)

Utilizando WHERE E ORDER BY juntos

Você já pode perceber que até as consultas mais simples nos permitem analisar os dados com precisão e flexibilidade para encontrar o que procuramos. Aprendemos a usar as palavras chaves AND e OR para definir mais de uma condição ao selecionar dados. E ainda aprendemos a utilizar a declaração WHERE e organizar os dados com a declaração ORDER BY.
Agora vamos combinar o que aprendemos nesse tutorial num exemplo. O SQL é específico quanto à ordem das palavras chaves, então siga essa ordem:

SELECT nome_colunas
FROM nome_tabelas
WHERE condição
ORDER BY nome_colunas;

Veja um exemplo utilizando os conhecimentos que você acabou de adquirir:

MariaDB [meu_banco_de_dados]> SELECT p_nome, profissao, salario
    -> FROM funcionarios
    -> WHERE p_nome LIKE 'Mar' OR salario > 3400
    -> ORDER BY id DESC;
+---------+-------------------+---------+
| p_nome  | profissao         | salario |
+---------+-------------------+---------+
| Fabiana | Vendedor          |    6500 |
| Marisa  | Gerente           |    9000 |
| Mariana | Diretor           |    5000 |
| Maria   | Gerente de vendas |    8500 |
+---------+-------------------+---------+
4 rows in set (0.001 sec)

Note que não selecionamos a coluna id, mas podemos utilizá-la com a declaração ORDER BY.

sexta-feira, 14 de agosto de 2020

Criando seu primeiro banco de dados e tabela com SQL

Photo by Jeremy Manoto on Unsplash

A linguagem SQL oferece mais do que um meio de obter informações de um banco de dados. Com ela podemos definir as estruturas que serão utilizadas para guardar e organizar os dados. A principal estrutura e a TABLE (tabela).
Uma tabela funciona como uma grade, com linhas e colunas. Essas linhas e colunas criam células (como no Excel), onde podemos armazenar os dados. As linhas possuem colunas e, colunas armazenam dados. Os dados mais comuns são do tipo números, datas e strings (cadeia de caracteres). A linguagem SQL nos permite criar uma estrutura de tabela e definir como essa tabela se relaciona com outras no banco de dados. Outro uso comum do SQL é fazer consultas, para extrair dados, das tabelas.
Tabela é a principal estrutura que você deve aprender para entender os dados do banco de dados. Quando começar a trabalhar com um banco de dados novo, a primeira coisa que você deve fazer é olhar as tabelas. Procure por algo que possa chamar sua atenção nos nomes das tabelas e na estrutura das colunas. A coluna contem texto, número ou os dois? Qual é a quantidade de linhas em cada tabela?
Em seguida, veja quantas tabelas existem. O mais simples dos bancos de dados pode ter apenas uma tabela. Um banco de dados que armazena dados de clientes pode ter dezenas de tabelas, até mesmo centenas. Com essa informação você vai saber o quanto de dados você vai precisar analisar.

Criando um banco de dados com SQL

Os programas que vamos utilizar para nesse tutorial é o MariaDB e o MySQL. Esses programas são conhecidos como sistemas de gerenciamento de banco de dados. Com esses softwares podemos definir, criar e consultar bancos de dados. Ao instalar um desses programas, ele vai criar um servidor de banco de dados que já possui um banco de dados chamado mysql. Esse banco de dados contêm objetos que inclui usuários, tabelas e muito mais.
Nesse tutorial de SQL, e nos próximos, vamos usar o MariaDB e o MySQL a partir do terminal (Linux) e Prompt de Comando (Windows). Você pode utilizar tanto o MySQL quanto o MariaDB. A diferença entre os dois é quase só o nome.
Depois de instalar, qualquer um dos dois programas, digite mysql no terminal ou no prompt de comando. Você deve ver uma tela parecida com essa: 

Para ver os bancos de dados use a declaração SHOW DATABASES;. Esse comando vai lista todos os bancos de dados presentes na sua máquina. 

Não vamos mexer com nenhum desses bancos de dados, vamos criar o nosso próprio banco de dados. Para fazer isso precisamos digitar apenas uma linha: CREATE DATABASE meu_banco_de_dados;

Para criar um novo banco de dados utilizamos duas palavras chaves - CREATE e DATABASE - seguido pelo nome do banco de dados. Após o nome do novo banco de dados, terminamos a instrução com ponto e vírgula. O ponto e vírgula é utilizado para encerrar todas as instruções da linguagem SQL.
Agora que criamos um banco de dados vamos olhar os bancos de dados novamente e ver o nosso banco de dados meu_banco_de_dados

Criando uma tabela com SQL

É nas tabelas que os dados são armazenados e o relacionamento definido. Para criar uma tabela precisamos informar o seu nome e o tipo de dados que essa coluna vai guardar. O tipo de dado de uma coluna é muito importante, é esse tipo de dado que defini quais dados podem ser guardados na coluna. Por exemplo, uma coluna do tipo numérico, se você tentar guardar dados do tipo data ou texto vai gerar um erro.
Podemos acessar e analisar os dados das tabelas com declarações SQL. Também podemos visualizar e alterar os dados da tabela facilmente, se suas necessidades mudarem mais tarde.
Agora vamos criar uma tabela no nosso banco de dados meu_banco_de_dados.

Declaração CREATE TABLE do SQL

Vamos criar uma tabela dentro do nosso banco de dados para guardar informações sobre funcionários. As informações que vamos guardar são básicas: nome, salário, profissão, etc. Nesse primeiro momento vamos criar apenas a estrutura pra guardar os dados. É isso que a declaração CREATE TABLE faz, cria uma estrutura, uma tabela.
Antes de criar uma tabela, precisamos definir em qual banco de dados a tabela será criada. Fazemos isso usando a declaração USE. Veja abaixo, um exemplo de como selecionar o banco de dados e criar uma tabela com SQL:

Agora vamos entender o que acabamos de fazer. A declaração USE seleciona o banco de dados. Com a declaração CREATE TABLE funcionarios (...); criamos uma tabela com o nome funcionarios. Dentro dos parênteses, da declaração CREATE TABLE, definimos os nomes das colunas e o tipo de dados que essa coluna vai guardar. A primeira coluna é a de id. Essa coluna vai guardar somente dados do tipo inteiro (1, 2, 3, etc). Na segunda linha, dentro dos parênteses, criamos uma coluna chamada u_nome e definimos que ela vai guardar até 25 caracteres (a, b, c, 1, 23, #, etc). A coluna data_inicio vai guardar dados do tipo data (DD-MM-AAAA). E por fim a coluna salario vai guardar dados do tipo numérico (1, 0.23, 7865, etc).

Declaração INSERT do SQL

Para inserir dados numa tabela usamos a declaração INSERT INTO nome_da_tabela. Nessa declaração também definimos quais colunas vão receber valores. Veja o exemplo abaixo:

Na primeira linha definimos em qual tabela vamos inserir os dados. Na segunda linha definimos quais colunas vão receber os dados. VALUES indica o conjunto de valores que vão ser guardados na tabela. Cada conjunto de valores com o id, p_nome, u_nome, profissao, data_inicio e salario é passado entre parênteses e separados por vírgula. Note que todas essas linhas fazem parte de uma instrução, por isso só existe um ponto e vírgula. Essa instrução pode ser escrita numa linhas apenas.
Para ver os dados gravados use a declaração SELECT * FROM funcionarios;. Vamos aprender a utilizar essa declaração no próximo tutorial.