Skip to content

Instantly share code, notes, and snippets.

@BrightMilk
Last active July 25, 2022 06:56
Show Gist options
  • Select an option

  • Save BrightMilk/9801085164ba5535d5f9e61dadb5ef0e to your computer and use it in GitHub Desktop.

Select an option

Save BrightMilk/9801085164ba5535d5f9e61dadb5ef0e to your computer and use it in GitHub Desktop.
Задание №1 для B2B-Center

Решение задания 1

Оптимизация хранения данных

Хранение информации о поле

Лучший способ для хранения информации о поле - использовать справочную таблицу возможных значений. Можно расширять таблицу по мере необходимости в новых значениях пола. Таким образом, в будущем получится избежать возможных проблем с определением гендерной принадлежности и, например, процессом смене пола. Также все-таки лучше не использовать null-значения для пола - можно указать в качестве дефолтного значение не определенного пола из справочника.

Хранение даты рождения

Дату рождения лучше хранить в формате DATE, например, 1970-01-01.

Если хранить дату рождения в формате TIMESTAMP (unixtime), то стоит учитывать, что TIMESTAMP имеет диапазон от «1970-01-01 00:00:01» до «2038-01-19 03:14:07» (UTC), поэтому в большинстве случаев он не подходит для даты рождения.

Можно использовать DATETIME, но тогда появляется необходимость со стороны пользователя заполнять также время рождения (что, как мне кажется, избыточно). Если такой необходимости нет - нужно использовать DATE.

Также вышеперечисленные типы данных используют различное количество памяти для хранения значений:

+------------+----------+
| DATE:      | 3 bytes  |
| TIMESTAMP: | 4 bytes	|
| DATETIME:  | 8 bytes	|
+------------+----------+

Схема БД

CREATE TABLE db.`user` (
	id INT auto_increment NOT NULL,
	name varchar(100) NOT NULL,
	gender_id INT DEFAULT 0 NOT NULL,
	birthdate DATE NOT NULL,
	CONSTRAINT user_PK PRIMARY KEY (id)
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_general_ci;

CREATE TABLE db.gender (
	id INT auto_increment NOT NULL,
	name varchar(100) NOT NULL,
	description varchar(100) NULL,
	CONSTRAINT gender_PK PRIMARY KEY (id)
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_general_ci;

CREATE TABLE db.phone_number (
	id INT auto_increment NOT NULL,
	`number` varchar(255) NOT NULL,
	user_id INT NOT NULL,
	CONSTRAINT phone_number_PK PRIMARY KEY (id),
	
)
ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_general_ci;

ALTER TABLE db.`user` ADD CONSTRAINT user_FK FOREIGN KEY (gender_id) REFERENCES db.gender(id);
ALTER TABLE db.`phone_number` ADD CONSTRAINT phone_number_FK FOREIGN KEY (user_id) REFERENCES db.`user`(id);

Тестовые данные

INSERT INTO db.gender (name,description)
	VALUES ('unknown','Не определено'),
	VALUES ('male','Мужчина'),
	VALUES ('female','Женщина');
	
INSERT INTO db.`user` (name,gender_id,birthdate)
	VALUES ('Yvonne Mcdowell',2,'1979-10-09'),
	VALUES ('Lareina Harrington',2,'2001-03-22'),
	VALUES ('Carl Espinoza',1,'1999-01-01'),
	VALUES ('Mallory Buck',2,'2002-12-02'),
	VALUES ('Althea Morton',2,'2001-09-17'),
	VALUES ('Shannon Fry',2,'1992-07-12'),
	VALUES ('Chaim Rogers',1,'2002-11-11'),
	VALUES ('Rachel Payne',2,'2001-08-13'),
	VALUES ('Matthew Casey',1,'2000-10-25'),
	VALUES ('Baxter Thornton',1,'1998-06-09');

INSERT INTO db.phone_number (`number`,user_id)
	VALUES ('(667) 281-8687',1),
	VALUES ('1-922-306-2043',2),
	VALUES ('1-232-249-6217',3),
	VALUES ('1-604-197-3522',4),
	VALUES ('(279) 852-2417',5),
	VALUES ('(218) 766-7412',6),
	VALUES ('(502) 213-6740',7),
	VALUES ('1-344-205-3086',8),
	VALUES ('1-380-420-6513',9),
	VALUES ('(782) 347-5271',10),
	VALUES ('(876) 626-2755',4),
	VALUES ('(846) 528-8542',8),
	VALUES ('1-422-658-7136',2),
	VALUES ('1-168-395-6412',4),
	VALUES ('(451) 437-3685',5),
	VALUES ('1-222-623-1235',2),
	VALUES ('1-713-424-7400',3);

Выполнение запроса

Запрос, возвращающий имя и число указанных телефонных номеров девушек в возрасте от 18 до 22 лет, выглядит следующим образом:

SELECT u.`name`, count(pn.`id`) AS `amount of phone numbers` FROM testovoe.`user` u 
	JOIN testovoe.`phone_number` pn ON pn.`user_id` = u.`id`
WHERE u.`gender_id` = 3 AND TIMESTAMPDIFF(YEAR, u.`birthdate`, CURDATE()) BETWEEN 18 AND 22
GROUP BY pn.`user_id`;

Результат:

+--------------------+-------------------------+
| name               | amount of phone numbers |
+--------------------+-------------------------+
| Lareina Harrington |                       3 |
| Mallory Buck       |                       3 |
| Althea Morton      |                       2 |
| Rachel Payne       |                       2 |
+--------------------+-------------------------+
4 rows in set (0.001 sec)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment