Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Technical Portfolio
GitHub & GitVerse Pages

Глава 4. Фильтрация

SQL Lab in JupyterLab

Data & BI Analyst

Abstract

В последнем запросе главы, в разделе Этот таинственный null, увидим причину, по которой для усечения строк в дальнейшем будет использоваться Pandas.

from sqlalchemy import create_engine
from sqlalchemy.engine import URL


connection_url = URL.create(
    drivername="mysql+pymysql",
    host="localhost",
    port=3306,
    database="sakila",
    username="root",
    password="*UHB5rdx",
)

engine = create_engine(connection_url)

%load_ext sql

%config SqlMagic.displaylimit = 20
%config SqlMagic.displaycon = False
# %config SqlMagic.feedback = False

%sql engine

print("SQLAlchemy - подключение создано")
print("JupySQL - успешно подключен через SQLAlchemy Engine!")
SQLAlchemy - подключение создано
JupySQL - успешно подключен через SQLAlchemy Engine!

Вычисление условий

-- Разделение условий оператором `AND`
WHERE first_name = 'STEVEN' AND create_date > '2006-01-01`

-- Разделение условий оператором `OR`
WHERE first_name = 'STEVEN' OR create_date > '2006-01-01`

-- Использование скобок
WHERE (first_name = 'STEVEN' OR last_name = 'YOUNG')
  AND create_date > '2006-01-01')

-- Использование оператора `NOT`
WHERE NOT (first_name = 'STEVEN' OR last_name = 'YOUNG')
  AND create_date > '2006-01-01')

-- Аналог без оператора `NOT`
WHERE first_name <> 'STEVEN' AND last_name <> 'YOUNG'    -- OR заменен на AND !
  AND create_date > '2006-01-01'

Построение условия

Условие состоит из одного или нескольких выражений в сочетании с одним или несколькими операторами.

Типы условий

Условия равенства

title = 'RIVER OUTLAW'
fed_id = '111-11-1111'
amount = 375.25
film_id = (SELECT film_id FROM film WHERE title = 'RIVER OUTLAW')
%%time
%%sql
SELECT c.email
FROM customer c
  INNER JOIN rental r
  ON c.customer_id = r.customer_id
WHERE date(r.rental_date) = '2005-06-14';
Loading...
CPU times: total: 0 ns
Wall time: 45 ms
Loading...

Условия неравенства

import polars as pl
print(f"Polars ver. {pl.__version__}")
Polars ver. 1.43.1
%config SqlMagic.autopolars = True
%%sql
SELECT c.email
FROM customer c
  INNER JOIN rental r
  ON c.customer_id = r.customer_id
WHERE date(r.rental_date) <> '2005-06-14';
Loading...
Loading...
-- Модификация условий равенства/неравенства

DELETE FROM rental
WHERE year(rental_date) = 2024;

DELETE FROM rental
WHERE year(rental_date) <> 2005 AND year(rental_date) <> 2006;

Условие диапазона

%%sql
SELECT customer_id, rental_id
FROM rental
WHERE rental_date < '2005-05-25';
Loading...
Loading...
%%sql
SELECT customer_id, rental_date
FROM rental
WHERE rental_date <= '2005-06-16'
  AND rental_date >= '2005-06-14';
Loading...
Loading...

Оператор beetween

%%sql
SELECT customer_id, rental_date
FROM rental
WHERE rental_date BETWEEN '2005-06-14' AND '2005-06-16';
Loading...
Loading...

Поскольку не указываем компонент времени, а время по умолчанию полночь, то диапазон длится от 2005-06-14 00:00:00 до 2005-06-16 00:00:00 и включает все фильмы взятые напрокат 14 или 15 июня.

Всегда необходимо указывать сначала нижнюю границу диапазона, затем верхнюю.
Верхняя и нижняя границы указаны включительно.

%%sql
SELECT customer_id, rental_date
FROM rental
WHERE rental_date BETWEEN '2005-06-16' AND '2005-06-14';
Loading...
%%sql
SELECT customer_id, rental_date
FROM rental
WHERE rental_date >= '2005-06-16'
  AND rental_date <= '2005-06-14';
Loading...
%%sql
SELECT customer_id, payment_id, amount
FROM payment
WHERE amount BETWEEN 10.0 AND 11.99;
Loading...
Loading...

Строковые диапазоны

%%sql
SELECT last_name, first_name
FROM customer
WHERE last_name BETWEEN 'FA' AND 'FR';
Loading...
Loading...

Фамилии начинающиеся с FR не попали в результат, т.к. находятся за пределами диапазона. Можем расширить диапазон:

%%sql
SELECT last_name, first_name
FROM customer
WHERE last_name BETWEEN 'FA' AND 'FRB';
Loading...
Loading...

Условия членства

%%sql
SELECT title, rating
FROM film
WHERE rating = 'G' OR rating = 'PG';
Loading...
Loading...

Оператор in

%%sql
SELECT title, rating
FROM film
WHERE rating IN ('G', 'PG');
Loading...
Loading...

Использование подзапросов

%%sql
SELECT title, rating
FROM film
WHERE rating IN (SELECT rating FROM film WHERE title LIKE '%PET%');
Loading...
Loading...
-- Пояснение подзапроса
SELECT title, rating FROM film WHERE title LIKE '%PET%';

| title           | rating |
| --------------- | ------ |
| "MALKOVICH PET" | "G"    |
| "MUPPET MILE"   | "PG"   |
| "PET HAUNTING"  | "PG"   |

Использование not in

%%sql
SELECT title, rating
FROM film
WHERE rating NOT IN ('PG-13', 'R', 'NC-17');

Условия соответствия

%%sql
SELECT last_name, first_name
FROM customer
WHERE left(last_name, 1) = 'Q';
Loading...
Loading...

Использование подстановочных знаков

%%sql
SELECT last_name, first_name
FROM customer
WHERE last_name LIKE '_A_T%S';
Loading...
Loading...
%%sql
SELECT last_name, first_name
FROM customer
WHERE last_name LIKE 'Q%' OR last_name LIKE 'Y%';
Loading...
Loading...

Использование регулярных выражений

%%sql
SELECT last_name, first_name
FROM customer
WHERE last_name REGEXP '^[QY]';
Loading...
Loading...

Этот таинственный null

%%sql
SELECT rental_id, customer_id
FROM rental
WHERE return_date IS NULL;
Loading...
Loading...

Выражение может быть null, но оно никогда не может быть равным null:

%%sql
SELECT rental_id, customer_id
FROM rental
WHERE return_date = NULL;
Loading...
%%sql
SELECT rental_id, customer_id, return_date
FROM rental
WHERE return_date IS NOT NULL;
Loading...
Loading...
%%sql
SELECT rental_id, customer_id, return_date
FROM rental
WHERE return_date NOT BETWEEN '2005-05-01' AND '2005-09-01';
Loading...
Loading...
%%sql
SELECT rental_id, customer_id, return_date
FROM rental
WHERE return_date IS NULL
  OR return_date NOT BETWEEN '2005-05-01' AND '2005-09-01';

Polars выдал ошибку ComputeError. Очистил длинный вывод через Clear Cell Output и добавил заметку:

%config SqlMagic.autopolars = False
import pandas as pd
print(f"Pandas ver. {pd.__version__}")
Pandas ver. 3.0.3
%config SqlMagic.autopandas = True
%%sql
SELECT rental_id, customer_id, return_date
FROM rental
WHERE return_date IS NULL
  OR return_date NOT BETWEEN '2005-05-01' AND '2005-09-01';
Loading...
Loading...

Упражнения

Предлагаемые упражнения призваны закрепить понимание условий фильтрации. В первых двух упражнениях потребуется подмножество строк из таблицы payment:

| payment_id | customer_id | amount | date(payment date) |
| ---------- | ----------- | ------ | ------------------ |
| 101        | 4           | 8.99   | 2005-08-19         |
| 102        | 4           | 1.99   | 2005-08-19         |
| 103        | 4           | 2.99   | 2005-08-20         |
| 104        | 4           | 6.99   | 2005-08-20         |
| 105        | 4           | 4.99   | 2005-08-21         |
| 106        | 4           | 2.99   | 2005-08-22         |
| 107        | 4           | 1.99   | 2005-08-23         |
| 108        | 5           | 0.99   | 2005-05-29         |
| 109        | 5           | 6.99   | 2005-05-31         |
| 110        | 5           | 1.99   | 2005-05-31         |
| 111        | 5           | 3.99   | 2005-06-15         |
| 112        | 5           | 2.99   | 2005-06-16         |
| 113        | 5           | 4.99   | 2005-06-17         |
| 114        | 5           | 2.99   | 2005-06-19         |
| 115        | 5           | 4.99   | 2005-06-20         |
| 116        | 5           | 4.99   | 2005-07-06         |
| 117        | 5           | 2.99   | 2005-07-08         |
| 118        | 5           | 4.99   | 2005-07-09         |
| 119        | 5           | 5.99   | 2005-07-09         |
| 120        | 5           | 1.99   | 2005-07-09         |

Упражнение 4.1

Какие из идентификаторов платежей будут возвращены при следующих условиях фильтрации?

customer_id <> 5
  AND (amount > 8 OR date(payment_date) = '2005-08-23')
| payment_id | customer_id | amount | date(payment date) |
| ---------- | ----------- | ------ | ------------------ |
| 101        | 4           | 8.99   | 2005-08-19         |
| 107        | 4           | 1.99   | 2005-08-23         |

Упражнение 4.2

Какие из идентификаторов платежей будут возвращены при следующих условиях фильтрации?

customer_id = 5 AND
  NOT (amount > 6 OR date(payment_date) = '2005-06-19')
| payment_id | customer_id | amount | date(payment date) |
| ---------- | ----------- | ------ | ------------------ |
| 108        | 5           | 0.99   | 2005-05-29         |
| 110        | 5           | 1.99   | 2005-05-31         |
| 111        | 5           | 3.99   | 2005-06-15         |
| 112        | 5           | 2.99   | 2005-06-16         |
| 113        | 5           | 4.99   | 2005-06-17         |
| 115        | 5           | 4.99   | 2005-06-20         |
| 116        | 5           | 4.99   | 2005-07-06         |
| 117        | 5           | 2.99   | 2005-07-08         |
| 118        | 5           | 4.99   | 2005-07-09         |
| 119        | 5           | 5.99   | 2005-07-09         |
| 120        | 5           | 1.99   | 2005-07-09         |

Упражнение 4.3

Создайте запрос, который извлекает из таблицы payments все строки, в которых сумма равна 1.98, 7.98 или 9.98.

%%sql
SELECT amount
FROM payment
WHERE amount IN (1.98, 7.98, 9.98)
Loading...
Loading...

Упражнение 4.4

Создайте запрос, который находит всех клиентов, в фамилиях которых содержится буква А во второй позиции и буква W – в любом месте после А.

%%sql
SELECT first_name, last_name
FROM customer
WHERE last_name LIKE '_A%W%'
ORDER BY last_name;
Loading...
Loading...