C, PHP, VB, .NET

Дневникът на Филип Петров


* UNION

Публикувано на 20 май 2009 в раздел Бази от Данни.

Не споменахме една пренебрегната досега възможност на SQL, а именно – обединението. То се използва, за да може две или повече SELECT заявки да бъдат комбинирани в една резултатна таблица. Нека преди да демонстрираме да създадем една примерна база от данни:

CREATE DATABASE unions;

CREATE TABLE vegetables(
	`id` INT NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(255) NULL DEFAULT NULL,
	`price` DOUBLE NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
);

CREATE TABLE fruits(
	`id` INT NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(255) NULL DEFAULT NULL,
	`price` DOUBLE NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
);

INSERT INTO vegetables(`id`, `name`, `price`)
VALUES 	(NULL, 'krastavici', 4.00),
	(NULL, 'domati', 5.00),
	(NULL, 'kartofi', 3.00);

INSERT INTO fruits(`id`, `name`, `price`)
VALUES 	(NULL, 'banani', 3.00),
	(NULL, 'iagodi', 2.50),
	(NULL, 'chereshi', 7.00);

Сега искаме да създадем таблица, която да изведе имената както на плодовете, така и на зеленчуците. Познатия досега вариант е с използване на JOIN, но така таблицата ще бъде с две колони. Ако искаме резултата да е подреден в една колона, то използваме UNION:

(SELECT name as Fruits_and_veggies
FROM vegetables)
UNION
(SELECT name
FROM fruits);
+--------------------+
| Fruits_and_veggies |
+--------------------+
| krastavici         |
| domati             |
| kartofi            |
| banani             |
| iagodi             |
| chereshi           |
+--------------------+
6 rows in set (0.00 sec)

Както виждате името на колоната се приема за името от първата таблица. Естествено можем да направим UNION и по две колони:

(SELECT name as Fruits_and_veggies, price
FROM vegetables)
UNION
(SELECT name, price
FROM fruits);
+--------------------+-------+
| Fruits_and_veggies | price |
+--------------------+-------+
| krastavici         |     4 |
| domati             |     5 |
| kartofi            |     3 |
| banani             |     3 |
| iagodi             |   2.5 |
| chereshi           |     7 |
+--------------------+-------+
6 rows in set (0.00 sec)

Не е задължително данните да са от един и същ тип. Важно е обаче броя на колоните от първия SELECT да съвпада с броя на колоните на втория! В противен случай няма как да се извърши обединението.

След като натрупате опит в използването на UNION рано или късно ще достигнете до един първоначално изглеждащ странен ефект – дублиращите се редове автоматично се премахват! Ето един пример:

(SELECT price
FROM vegetables)
UNION
(SELECT price
FROM fruits);
+-------+
| price |
+-------+
|     4 |
|     5 |
|     3 |
|   2.5 |
|     7 |
+-------+
5 rows in set (0.00 sec)

Знаем, че имаме общо 6 плода и зеленчука в таблиците, а в резултата от цените излязоха само 5. Това е така, защото цената на banani и kartofi е една и съща и UNION е премахнал дублиращите се редове. Ако това предизвиква потенциален проблем във вашата заявка, то трябва да използвате допълнителната дума ALL:

(SELECT price
FROM vegetables)
UNION ALL
(SELECT price
FROM fruits);
+-------+
| price |
+-------+
|     4 |
|     5 |
|     3 |
|     3 |
|   2.5 |
|     7 |
+-------+
6 rows in set (0.00 sec)

Естествено възможно е UNION да е част от под-заявка (например вложен SELECT). Затова ограждането на заявките в скоби не е задължително, но е силно препоръчително.

 



Добави коментар

Адресът на електронната поща няма да се публикува


*