Consultas de Selección: DISTINCT, WHERE, LIMIT, FETCH

Conexión a la Base de Datos

[1]:
import pandas as pd
import psycopg2
import sqlalchemy
import matplotlib as plt

%matplotlib inline

from sqlalchemy import create_engine

POSTGRES_ADDRESS = 'localhost' # Este es el servidor, puede ser una IP
POSTGRES_PORT = '5432'
POSTGRES_USERNAME = 'postgres'
POSTGRES_PASSWORD = '1234'
POSTGRES_DBNAME = 'dvdrental'

# Ahora se configura la cadena de conexión.
# Esta es una cadena que contiene los parámetros necesarios para establecer una
# conexión con posgres.
postgres_str = ('postgresql://{username}:{password}@{ipaddress}:{port}/{dbname}'.format(username=POSTGRES_USERNAME,
                                                                                        password=POSTGRES_PASSWORD,
                                                                                        ipaddress=POSTGRES_ADDRESS,
                                                                                        port=POSTGRES_PORT,
                                                                                        dbname=POSTGRES_DBNAME))
# A continuación se crea la conexión
cnx = create_engine(postgres_str)

La Cláusula DISTINCT

Esta cláusula se utiliza en la declaración SELECT para eliminar filas duplicadas de un conjunto de resultados. NO las elimina de la tabla. DISTINCT mantiene una fila para cada grupo de duplicados, se puede aplicar a una o más columnas en la lista de selección de la consulta SELECT.

[2]:
#Crearemos una tabla para este ejemplo
sql = ''' CREATE TABLE colores (
            id serial NOT NULL PRIMARY KEY,
            primerColor VARCHAR,
            segundoColor VARCHAR ); '''

cnx.execute(sql)

# Revisemos el concepto de SERIAL en Postgres http://sqlines.com/postgresql/datatypes/serial
[2]:
<sqlalchemy.engine.result.ResultProxy at 0x1cae2792850>
[3]:
# Insertamos algunos registros
sql = ''' INSERT INTO colores (primerColor, segundoColor)
            VALUES  ('rojo', 'rojo'), ('rojo', 'rojo'),
                    ('rojo', NULL),(NULL, 'rojo'),
                    ('rojo', 'verde'),('rojo', 'azul'),
                    ('verde', 'rojo'),('verde', 'azul'),
                    ('verde', 'verde'),('azul', 'rojo'),
                    ('azul', 'verde'),('azul', 'azul'); '''

cnx.execute(sql)
[3]:
<sqlalchemy.engine.result.ResultProxy at 0x1cadfecb9d0>
[4]:
# Consultamos los registros insertados
SQL = '''SELECT id, primerColor, segundoColor from colores;'''

pd.read_sql_query(SQL, cnx)
[4]:
id primercolor segundocolor
0 1 rojo rojo
1 2 rojo rojo
2 3 rojo None
3 4 None rojo
4 5 rojo verde
5 6 rojo azul
6 7 verde rojo
7 8 verde azul
8 9 verde verde
9 10 azul rojo
10 11 azul verde
11 12 azul azul
[5]:
# Cuáles son los colores disponibles en como primerColor
sql = ''' SELECT
            DISTINCT primerColor
        FROM colores
        ORDER BY primerColor;'''

pd.read_sql_query(sql, cnx)
[5]:
primercolor
0 azul
1 rojo
2 verde
3 None
[6]:
# Cuáles son las combinaciones únicas de color 1 y 2
sql = ''' SELECT
            DISTINCT primerColor, segundoColor
        FROM colores
        ORDER BY primerColor, segundoColor;'''

pd.read_sql_query(sql, cnx)
[6]:
primercolor segundocolor
0 azul azul
1 azul rojo
2 azul verde
3 rojo azul
4 rojo rojo
5 rojo verde
6 rojo None
7 verde azul
8 verde rojo
9 verde verde
10 None rojo
[7]:
# La siguiente declaración ordena el conjunto de resultados por color 1 y 2
# luego, para cada grupo de duplicados, mantiene la primera fila
# en el conjunto de resultados devuelto.

sql = ''' SELECT
            DISTINCT ON (primerColor) primerColor, segundoColor
        FROM colores
        ORDER BY primerColor, segundoColor;'''

pd.read_sql_query(sql, cnx)
[7]:
primercolor segundocolor
0 azul azul
1 rojo azul
2 verde azul
3 None rojo
[8]:
# ¿Qué hace la siguiente sentencia?

sql = ''' SELECT
            DISTINCT ON (primerColor) segundoColor
        FROM colores
        ORDER BY primerColor;'''

pd.read_sql_query(sql, cnx)
[8]:
segundocolor
0 azul
1 verde
2 verde
3 rojo
[9]:
#Eliminamos la tabla de ejemplo
sql = ''' DROP TABLE colores; '''

cnx.execute(sql)
[9]:
<sqlalchemy.engine.result.ResultProxy at 0x1cae30ecc70>

La Cláusula WHERE

La declaración SELECT devuelve todas las filas de una o más columnas en una tabla. Para seleccionar filas que satisfagan una condición específica, use la cláusula WHERE.

La consulta solo devuelve filas que cumplen con condición en la cláusula WHERE. Es decir, solo las filas que hacen que la condición de evaluación sea verdadera se incluirán en el conjunto de resultados.

El uso de esta cláusula es clave en la declaración UPDATE y DELETE para especificar las filas que se actualizarán o eliminarán. En caso de no especificarse, se actualizan o eliminan todas las filas lo cual conduce a pérdida de información o resultados indeseados.

Para formar la condición en la cláusula WHERE, se usan operadores de comparación y lógicos. Puedes consultar los operadores lógicos aquí.

[10]:
# Consultamos los clientes que sellamen Jamie y que su apellido no sea Rice
sql = ''' SELECT last_name, first_name
            FROM customer
            WHERE first_name = 'Jamie' AND last_name <> 'Rice';'''

pd.read_sql_query(sql, cnx)
[10]:
last_name first_name
0 Waugh Jamie
[11]:
# Consultamos los clientes que se llamen Jamie o que su nombre comience con FR
sql = ''' SELECT last_name, first_name
            FROM customer
            WHERE first_name = 'Jamie' OR first_name LIKE 'Fr%';'''

pd.read_sql_query(sql, cnx)
[11]:
last_name first_name
0 Parker Frances
1 Rice Jamie
2 Waggoner Frank
3 Wheat Fred
4 Sikes Francis
5 Isbell Frederick
6 Skidmore Francisco
7 Troutman Franklin
8 Waugh Jamie
9 Duggan Freddie
[12]:
# Consultamos los clientes que estén en una lista
sql = ''' SELECT last_name, first_name
            FROM customer
            WHERE first_name in ('Marion', 'Kelly', 'Willie');'''

pd.read_sql_query(sql, cnx)
[12]:
last_name first_name
0 Torres Kelly
1 Snyder Marion
2 Howell Willie
3 Markham Willie
4 Knott Kelly
5 Ocampo Marion
[13]:
# Consultamos los clientes cuyo nombre comience por A y la
# longitud de su nombre tenga entre 3 y 4 lentras

sql = '''
SELECT first_name, LENGTH(first_name) cantCaracteres
FROM customer
WHERE
        first_name LIKE 'A%' AND
        LENGTH(first_name) BETWEEN 3 AND 4
ORDER BY cantCaracteres;
'''

pd.read_sql_query(sql, cnx)
[13]:
first_name cantcaracteres
0 Ann 3
1 Ana 3
2 Amy 3
3 Alma 4
4 Adam 4
5 Alan 4
6 Alex 4
7 Andy 4
8 Anna 4
9 Anne 4
[14]:
# Consultar los montos pagados que NO estén entre 2 y 10 USD

sql = '''
SELECT customer_id, payment_id, amount
FROM payment
WHERE amount NOT BETWEEN 2 AND 10;
'''

pd.read_sql_query(sql, cnx)
[14]:
customer_id payment_id amount
0 341 17504 1.99
1 343 17514 0.99
2 343 17515 0.99
3 343 17518 0.99
4 344 17521 0.99
... ... ... ...
3427 229 32090 0.99
3428 234 32091 0.99
3429 236 32092 0.99
3430 251 32095 0.99
3431 263 32097 0.99

3432 rows × 3 columns

[15]:
# Consultar los pagos realizados entre el 7 y el 15 de febrero del 2007

sql = '''
SELECT customer_id, payment_id, amount, payment_date
FROM payment
WHERE payment_date BETWEEN '2007-02-07' AND '2007-02-15';
'''

pd.read_sql_query(sql, cnx)
[15]:
customer_id payment_id amount payment_date
0 368 17610 0.99 2007-02-14 23:25:11.996577
1 370 17617 6.99 2007-02-14 23:33:58.996577
2 402 17743 4.99 2007-02-14 23:53:34.996577
3 416 17793 2.99 2007-02-14 21:21:59.996577
4 432 17854 5.99 2007-02-14 23:07:27.996577
5 481 18051 2.99 2007-02-14 22:03:35.996577
6 512 18155 6.99 2007-02-14 22:57:03.996577
7 516 18173 4.99 2007-02-14 21:23:39.996577
8 546 18276 1.99 2007-02-14 23:10:43.996577
9 561 18322 2.99 2007-02-14 23:52:46.996577
10 592 18441 6.99 2007-02-14 21:41:12.996577
11 595 18456 2.99 2007-02-14 22:16:01.996577
12 1 18495 5.99 2007-02-14 23:22:38.996577
13 46 18686 4.99 2007-02-14 21:45:29.996577
14 49 18698 0.99 2007-02-14 21:44:52.996577
15 95 18870 2.99 2007-02-14 22:41:17.996577
16 119 18963 7.99 2007-02-14 23:05:16.996577
17 139 19036 2.99 2007-02-14 22:11:22.996577
18 173 19159 2.99 2007-02-14 23:32:33.996577
19 186 19212 4.99 2007-02-14 23:47:05.996577
20 191 19239 2.99 2007-02-14 22:23:12.996577
21 196 19257 5.99 2007-02-14 23:13:47.996577
22 197 19265 2.99 2007-02-14 22:43:41.996577
23 210 19293 2.99 2007-02-14 23:01:30.996577
24 239 19399 4.99 2007-02-14 21:29:00.996577
25 244 19421 6.99 2007-02-14 23:32:48.996577
26 264 19498 3.99 2007-02-14 21:44:53.996577

La cláusula Limit

Restringe el número de filas devueltas por la consulta. La cláusula LIMIT es ampliamente utilizada por muchos sistemas de administración de bases de datos relacionales como SQLite, Postgres, MySQL, H2 y HSQLDB.

[16]:
# COnsultar las últimas 5 películas en orden alfabético

sql = '''
SELECT film_id, title, release_year
FROM film
ORDER BY title desc
LIMIT 5;
'''

pd.read_sql_query(sql, cnx)
[16]:
film_id title release_year
0 1000 Zorro Ark 2006
1 999 Zoolander Fiction 2006
2 998 Zhivago Core 2006
3 997 Youth Kick 2006
4 996 Young Language 2006
[17]:
# COnsultar las últimas 5 películas en orden alfabético

sql = '''
SELECT film_id, title, release_year
FROM film
ORDER BY title
LIMIT 10;
'''

pd.read_sql_query(sql, cnx)
[17]:
film_id title release_year
0 1 Academy Dinosaur 2006
1 2 Ace Goldfinger 2006
2 3 Adaptation Holes 2006
3 4 Affair Prejudice 2006
4 5 African Egg 2006
5 6 Agent Truman 2006
6 7 Airplane Sierra 2006
7 8 Airport Pollock 2006
8 9 Alabama Devil 2006
9 10 Aladdin Calendar 2006
[18]:
# Consultar las 3 peliculas siguientes a las primeras 5.
# Es decir, omitir las primeras 5 y tomar las 3 siguientes.

sql = '''
SELECT film_id, title, release_year
FROM film
ORDER BY film_id
LIMIT 3 OFFSET 5;
'''

pd.read_sql_query(sql, cnx)
[18]:
film_id title release_year
0 6 Agent Truman 2006
1 7 Airplane Sierra 2006
2 8 Airport Pollock 2006
[19]:
# Consultar las 10 peliculas con el alquiler mas caro

sql = '''
SELECT film_id, title, rental_rate
FROM film
ORDER BY rental_rate DESC
LIMIT 10;
'''

pd.read_sql_query(sql, cnx)
[19]:
film_id title rental_rate
0 13 Ali Forever 4.99
1 20 Amelie Hellfighters 4.99
2 7 Airplane Sierra 4.99
3 10 Aladdin Calendar 4.99
4 2 Ace Goldfinger 4.99
5 8 Airport Pollock 4.99
6 98 Bright Encounters 4.99
7 133 Chamber Italian 4.99
8 384 Grosse Wonderful 4.99
9 21 American Circus 4.99

Cláusula FETCH

La cláusula LIMIT no es un estándar SQL. Para cumplir con el estándar SQL, PostgreSQL admite la cláusula FETCH para recuperar una cantidad de filas devueltas por una consulta. Tenga en cuenta que la esta cláusula se introdujo en SQL versión 2008.

[20]:
# Tomar la primera fila

sql = '''
SELECT film_id, title
FROM film
ORDER BY title
FETCH FIRST ROW ONLY;
'''

pd.read_sql_query(sql, cnx)
[20]:
film_id title
0 1 Academy Dinosaur
[21]:
# Tomar las primeras 3, si se pone 1 es equivalente a la sentencia anterior

sql = '''
SELECT film_id, title
FROM film
ORDER BY title
FETCH FIRST 3 ROW ONLY;
'''

pd.read_sql_query(sql, cnx)
[21]:
film_id title
0 1 Academy Dinosaur
1 2 Ace Goldfinger
2 3 Adaptation Holes
[22]:
# Devuelve las siguientes tres películas después de las
# primeras cinco películas ordenadas por títulos

sql = '''
SELECT film_id, title
FROM film
ORDER BY title
OFFSET 5 ROWS
FETCH FIRST 3 ROW ONLY;
'''

pd.read_sql_query(sql, cnx)
[22]:
film_id title
0 6 Agent Truman
1 7 Airplane Sierra
2 8 Airport Pollock