- Накратко за обобщените таблици
- Обръщане на данни с помощта на инструменти (dbForge Studio за MySQL)
- Обръщане на данни чрез SQL
- Базиран на T-SQL пример за SQL Server
- Пример за MySQL
- Автоматизиране на завъртането на данните, динамично създаване на заявка
Накратко за обобщените таблици
Тази статия се занимава с трансформирането на данни от таблица от редове в колони. Такава трансформация се нарича въртящи се таблици. Често резултатът от централната част е обобщена таблица, в която статистическите данни са представени във формата, подходяща или необходима за отчет.
Освен това такава трансформация на данни може да бъде полезна, ако базата данни не е нормализирана и информацията се съхранява в нея в неоптимална форма. Така че, когато реорганизирате базата данни и прехвърляте данни в нови таблици или генерирате необходимо представяне на данни, опорната точка на данните може да бъде полезна, т.е. преместване на стойности от редове към получените колони.
По-долу е даден пример за старата таблица с продукти – ProductsOld и новата – ProductsNew. Именно чрез трансформацията от редове в колони може лесно да се постигне такъв резултат.
Ето пример за въртяща се таблица.

Обръщане на данни чрез инструменти (dbForge Studio за MySQL)
Има приложения, които имат инструменти, позволяващи да се внедри центриране на данни в удобна графична среда. Например dbForge Studio за MySQL включва функционалност на обобщени таблици, която осигурява желания резултат само с няколко стъпки.

Нека разгледаме примера с опростена таблица с поръчки – PurchaseOrderHeader .
СЪЗДАВАНЕ НА ТАБЛИЦА PurchaseOrderHeader ( PurchaseOrderID INT(11) НЕ НУЛЕН, EmployeeID INT(11) НЕ НУЛЕН, VendorID INT(11) НЕ НУЛЕН, ПЪРВИЧЕН КЛЮЧ (PurchaseOrderID));INSERT PurchaseOrderVALUE(EmployeePurderse11) , 258, 1580);INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeID, VendorID) СТОЙНОСТИ (2, 254, 1496);INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeID, VendorID,EmployeeID, VendorID,VerchaseurOrderID,VendorID,EmployeeID, VendorID,RechaseurOYe4); ) VALUES (4, 261, 1650);INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeID, VendorID) VALUES (5, 251, 1654);INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeRderID, EmployeeRTCa идентификатор на покупка, EmployeeRTCa идентификатор на поръчката, идентификатор на заемател, идентификатор на поръчката, идентификатор на поръчката, идентификатор на поръчката, идентификатор на поръчката, идентификатор на поръчката, идент. , EmployeeID, VendorID) VALUES (7, 255, 1678); INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeID, VendorID) VALUES (8, 256, 1616);INSERT PurchaseOrderHeader(PurchaseOrderHeader,Purchase2SQUEID, EmploIDyeder2, EmploIDyeder2); INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeID, VendorID) СТОЙНОСТИ (10, 250, 1602); INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeID, VendorID) СТОЙНОСТИ (11, 258, 1540);...
Да приемем, че трябва да направим избор от таблицата и да определим броя на поръчките, направени от определени служители от конкретни доставчици. Списъкът на служителите, за които е необходима информация – 250, 251, 252, 253, 254.
Предпочитан изглед за отчета е следният.

Лявата колона VendorID показва идентификационните номера на доставчиците; колони Emp250 , Emp251 , Emp252 , Emp253 и Emp254 показване на броя на поръчките.
За да постигнете това в dbForge Studio за MySQL, трябва да:
- Добавете таблицата като източник на данни за представянето на „Опорна таблица“ на документа. В Database Explorer щракнете с десния бутон върху PurchaseOrderHeader таблица и изберете Изпращане до и след това Опорна таблица в изскачащото меню.
- Посочете колона, чиито стойности ще бъдат редове. Плъзнете VendorID колона в полето „Отпуснете полетата на редовете тук“.
- Посочете колона, чиито стойности ще бъдат колони. Плъзнете EmployeeID колона в полето „Пусти полетата на колона тук“. Можете също да зададете филтър за необходимите служители (250, 251, 252, 253, 254).
- Посочете колона, чиито стойности ще бъдат данните. Плъзнете PurchaseOrderID колона в полето „Пусти елементи от данни тук“.
- В свойствата на PurchaseOrderID колона, посочете типа на агрегиране – Брой стойности .
Бързо получихме желания резултат.

Обръщане на данни чрез SQL
Разбира се, трансформацията на данни може да се извърши с помощта на база данни чрез писане на SQL заявка. Но има лек проблем, MySQL няма конкретно изявление, което позволява да се направи това.
Базиран на T-SQL пример за SQL Server
Например, SqlServer и Oracle имат оператора PIVOT, който позволява извършването на такава трансформация на данни. Ако работихме със SqlServer, нашата заявка би изглеждала така.
ИЗБЕРЕТЕ VendorID ,[250] КАТО Emp1 ,[251] КАТО Emp2 ,[252] КАТО Emp3 ,[253] КАТО Emp4 ,[254] КАТО Emp5FROM (ИЗБЕРЕТЕ PurchaseOrderID ,EmployeeID ,VendorID FROM Purchasing.PurTaderCOUNT) (PurchaseOrderID) FOR EmployeeID IN ([250], [251], [252], [253], [254])) КАТО ПОРЪЧКА ОТ t.VendorID;
Пример за MySQL
В MySQL ще трябва да използваме средствата на SQL. Данните трябва да бъдат групирани по колоната на доставчик – VendorID , и за всеки задължителен служител (EmployeeID ), трябва да създадете отделна колона с агрегатна функция.
В нашия случай трябва да изчислим броя на поръчките, така че ще използваме агрегатната функция COUNT.
В таблицата източник информацията за всички служители се съхранява в една колона EmployeeID , и трябва да изчислим броя на поръчките за конкретен служител, така че трябва да научим нашата агрегатна функция да обработва само определени редове.
Обобщаващата функция не отчита NULL стойности и ние използваме тази особеност за нашите цели.
Можете да използвате условния оператор IF или CASE, който ще върне конкретна стойност за желания служител, в противен случай просто ще върне NULL; в резултат на това функцията COUNT ще брои само стойности, различни от NULL.
Получената заявка е както следва:
SELECT VendorID, COUNT(IF(EmployeeID =250, PurchaseOrderID, NULL)) КАТО Emp250, COUNT(IF(EmployeeID =251, PurchaseOrderID, NULL)) КАТО Emp251, COUNT(IF(EmployeeID, Purse NULL) 25r ) КАТО Emp252, COUNT(IF(EmployeeID =253, PurchaseOrderID, NULL)) КАТО Emp253, COUNT(IF(EmployeeID =254, PurchaseOrderID, NULL)) КАТО Emp254FROM PurchaseOrderHeader.>Или дори така:
VendorID, COUNT(IF(EmployeeID =250, 1, NULL)) КАТО Emp250, COUNT(IF(EmployeeID =251, 1, NULL)) КАТО Emp251, COUNT(IF(EmployeeID =252, 1, NULL)) КАТО Emp252, COUNT(IF(EmployeeID =253, 1, NULL)) КАТО Emp253, COUNT(IF(EmployeeID =254, 1, NULL)) КАТО Emp254FROM PurchaseOrderHeader pWHERE p.EmployeeID МЕЖДУ ПРЕДПРЕДЕЛИТЕЛ 250 МЕЖДУ ГРУПАТА;При изпълнение се получава познат резултат.
![]()
Автоматизиране на центрирането на данните, динамично създаване на заявка
Както се вижда, заявката има определена последователност, тоест всички трансформирани колони се формират по подобен начин и за да напишете заявката, трябва да знаете конкретните стойности от таблицата. За да формирате основна заявка, трябва да прегледате всички възможни стойности и едва след това да напишете заявката. Като алтернатива можете да предадете тази задача на сървър, като го накарате да получи тези стойности и динамично да изпълнява рутинната задача.
Нека се върнем към първия пример, в който формирахме новата таблица ProductsNew от Стари продукти маса. Там стойностите на свойствата са ограничени и дори не можем да знаем всички възможни стойности; разполагаме само с информацията къде се съхраняват имената на имотите и тяхната стойност. Това са Свойството и Стойност колони, съответно.
Целият алгоритъм за създаване на SQL заявката се свежда до получаване на стойностите, от които ще се формират нови колони и конкатенации на непроменяеми части от заявката.
SELECT GROUP_CONCAT( CONCAT( ' MAX(IF(Property =''', t.Property, ''', Value, NULL)) AS ', t.Property ) ) INTO @PivotQueryFROM (ИЗБЕРЕТЕ Свойство ОТ ProductOld GROUP BY Свойство) t;SET @PivotQuery =CONCAT('SELECT ProductID,', @PivotQuery, ' ОТ ProductOld GROUP ПО ProductID');Променливата @PivotQuery ще съхранява нашата заявка, текстът е форматиран за по-голяма яснота.
ИЗБЕРЕТЕ ProductID, MAX(IF(Property ='Color', Value, NULL)) КАТО цвят, MAX(IF(Property ='Name', Value, NULL)) КАТО име, MAX(IF(Property ='ProductNumber) ', Стойност, NULL)) КАТО номер на продукт, MAX(IF(Property ='Size', Value, NULL)) КАТО размер, MAX(IF(Property ='SizeUnitMeasureCode', Value, NULL)) КАТО SizeUnitMeasureCodeFROM ProductIDСлед като го изпълним, ще получим желания резултат, съответстващ на схемата на таблицата ProductsNew.
Нещо повече, заявката от променлива @PivotQuery може да се изпълни в скрипта с помощта на MySQL оператор EXECUTE.препарат PREPARE ОТ @PivotQuery;изявление EXECUTE;изявление DEALLOCATE PREPARE;![]()