தரவுத்தளங்களின் உலகம் நீண்ட காலமாக SQL மொழியைப் பயன்படுத்தும் தொடர்புடைய DBMSகளால் ஆதிக்கம் செலுத்துகிறது. வளர்ந்து வரும் மாறுபாடுகள் NoSQL என்று அழைக்கப்படுகின்றன. இந்த சந்தையில் அவர்கள் தங்களுக்கு ஒரு குறிப்பிட்ட இடத்தை உருவாக்கிக் கொண்டனர், ஆனால் தொடர்புடைய DBMS கள் இறக்கப் போவதில்லை, மேலும் அவற்றின் நோக்கங்களுக்காக தொடர்ந்து தீவிரமாகப் பயன்படுத்தப்படுகின்றன.
இந்த கட்டுரையில் நான் ஒரு செயல்பாட்டு தரவுத்தளத்தின் கருத்தை விவரிக்க விரும்புகிறேன். சிறந்த புரிதலுக்காக, கிளாசிக்கல் ரிலேஷனல் மாடலுடன் ஒப்பிட்டு இதைச் செய்வேன். இணையத்தில் காணப்படும் பல்வேறு SQL சோதனைகளின் சிக்கல்கள் எடுத்துக்காட்டுகளாகப் பயன்படுத்தப்படும்.
அறிமுகம்
தொடர்புடைய தரவுத்தளங்கள் அட்டவணைகள் மற்றும் புலங்களில் இயங்குகின்றன. செயல்பாட்டு தரவுத்தளத்தில், வகுப்புகள் மற்றும் செயல்பாடுகள் முறையே பயன்படுத்தப்படும். N விசைகள் கொண்ட அட்டவணையில் உள்ள புலம் N அளவுருக்களின் செயல்பாடாக குறிப்பிடப்படும். அட்டவணைகளுக்கு இடையிலான உறவுகளுக்குப் பதிலாக, இணைப்பு செய்யப்பட்ட வகுப்பின் பொருள்களைத் திரும்பப் பெறும் செயல்பாடுகள் பயன்படுத்தப்படும். JOIN க்குப் பதிலாக செயல்பாட்டு கலவை பயன்படுத்தப்படும்.
பணிகளுக்கு நேரடியாகச் செல்வதற்கு முன், டொமைன் லாஜிக் பணியை விவரிக்கிறேன். DDLக்கு நான் PostgreSQL தொடரியல் பயன்படுத்துவேன். செயல்பாட்டுக்கு அதன் சொந்த தொடரியல் உள்ளது.
அட்டவணைகள் மற்றும் புலங்கள்
பெயர் மற்றும் விலை புலங்களைக் கொண்ட ஒரு எளிய Sku பொருள்:
உறவுமுறை
CREATE TABLE Sku
(
id bigint NOT NULL,
name character varying(100),
price numeric(10,5),
CONSTRAINT id_pkey PRIMARY KEY (id)
)
செயல்பாட்டு
CLASS Sku;
name = DATA STRING[100] (Sku);
price = DATA NUMERIC[10,5] (Sku);
நாங்கள் இரண்டை அறிவிக்கிறோம் செயல்பாடுகளை, இது ஒரு அளவுரு Sku ஐ உள்ளீடாக எடுத்து ஒரு பழமையான வகையை வழங்குகிறது.
ஒரு செயல்பாட்டு DBMS இல் ஒவ்வொரு பொருளும் தானாகவே உருவாக்கப்படும் மற்றும் தேவைப்பட்டால் அணுகக்கூடிய சில உள் குறியீடுகளைக் கொண்டிருக்கும் என்று கருதப்படுகிறது.
தயாரிப்பு/கடை/சப்ளையருக்கு விலையை நிர்ணயிப்போம். இது காலப்போக்கில் மாறக்கூடும், எனவே அட்டவணையில் நேர புலத்தைச் சேர்ப்போம். குறியீட்டைக் குறைக்க, தொடர்புடைய தரவுத்தளத்தில் உள்ள கோப்பகங்களுக்கான அட்டவணையை அறிவிப்பதைத் தவிர்க்கிறேன்:
உறவுமுறை
CREATE TABLE prices
(
skuId bigint NOT NULL,
storeId bigint NOT NULL,
supplierId bigint NOT NULL,
dateTime timestamp without time zone,
price numeric(10,5),
CONSTRAINT prices_pkey PRIMARY KEY (skuId, storeId, supplierId)
)
செயல்பாட்டு
CLASS Sku;
CLASS Store;
CLASS Supplier;
dateTime = DATA DATETIME (Sku, Store, Supplier);
price = DATA NUMERIC[10,5] (Sku, Store, Supplier);
குறியீடுகள்
கடைசி உதாரணத்திற்கு, அனைத்து விசைகளிலும் தேதியிலும் ஒரு குறியீட்டை உருவாக்குவோம், இதன் மூலம் ஒரு குறிப்பிட்ட நேரத்திற்கான விலையை விரைவாகக் கண்டறிய முடியும்.
உறவுமுறை
CREATE INDEX prices_date
ON prices
(skuId, storeId, supplierId, dateTime)
செயல்பாட்டு
INDEX Sku sk, Store st, Supplier sp, dateTime(sk, st, sp);
பணிகளை
தொடர்புடையவற்றிலிருந்து எடுக்கப்பட்ட ஒப்பீட்டளவில் எளிமையான சிக்கல்களுடன் ஆரம்பிக்கலாம்
முதலில், டொமைன் தர்க்கத்தை அறிவிப்போம் (தொடர்பு தரவுத்தளத்திற்கு இது மேலே உள்ள கட்டுரையில் நேரடியாக செய்யப்படுகிறது).
CLASS Department;
name = DATA STRING[100] (Department);
CLASS Employee;
department = DATA Department (Employee);
chief = DATA Employee (Employee);
name = DATA STRING[100] (Employee);
salary = DATA NUMERIC[14,2] (Employee);
சிக்கல் 1.1
உடனடி மேற்பார்வையாளரின் சம்பளத்தை விட அதிகமான சம்பளம் பெறும் ஊழியர்களின் பட்டியலைக் காண்பி.
உறவுமுறை
select a.*
from employee a, employee b
where b.id = a.chief_id
and a.salary > b.salary
செயல்பாட்டு
SELECT name(Employee a) WHERE salary(a) > salary(chief(a));
சிக்கல் 1.2
தங்கள் துறையில் அதிகபட்ச சம்பளம் பெறும் ஊழியர்களை பட்டியலிடுங்கள்
உறவுமுறை
select a.*
from employee a
where a.salary = ( select max(salary) from employee b
where b.department_id = a.department_id )
செயல்பாட்டு
maxSalary 'Максимальная зарплата' (Department s) =
GROUP MAX salary(Employee e) IF department(e) = s;
SELECT name(Employee a) WHERE salary(a) = maxSalary(department(a));
// или если "заинлайнить"
SELECT name(Employee a) WHERE
salary(a) = maxSalary(GROUP MAX salary(Employee e) IF department(e) = department(a));
இரண்டு செயலாக்கங்களும் சமமானவை. முதல் வழக்கில், ஒரு தொடர்புடைய தரவுத்தளத்தில் நீங்கள் CREATE VIEW ஐப் பயன்படுத்தலாம், அதே வழியில் ஒரு குறிப்பிட்ட துறைக்கான அதிகபட்ச சம்பளத்தை முதலில் கணக்கிடும். பின்வருவனவற்றில், தெளிவுக்காக, நான் முதல் வழக்கைப் பயன்படுத்துவேன், ஏனெனில் இது தீர்வை சிறப்பாக பிரதிபலிக்கிறது.
சிக்கல் 1.3
டிபார்ட்மென்ட் ஐடிகளின் பட்டியலைக் காட்டவும், அதில் 3 பேருக்கு மேல் இல்லாத ஊழியர்களின் எண்ணிக்கை.
உறவுமுறை
select department_id
from employee
group by department_id
having count(*) <= 3
செயல்பாட்டு
countEmployees 'Количество сотрудников' (Department d) =
GROUP SUM 1 IF department(Employee e) = d;
SELECT Department d WHERE countEmployees(d) <= 3;
சிக்கல் 1.4
அதே துறையில் பணிபுரியும் நியமிக்கப்பட்ட மேலாளர் இல்லாத ஊழியர்களின் பட்டியலைக் காண்பி.
உறவுமுறை
select a.*
from employee a
left join employee b on (b.id = a.chief_id and b.department_id = a.department_id)
where b.id is null
செயல்பாட்டு
SELECT name(Employee a) WHERE NOT (department(chief(a)) = department(a));
சிக்கல் 1.5
அதிகபட்ச மொத்த ஊழியர் சம்பளத்துடன் துறை ஐடிகளின் பட்டியலைக் கண்டறியவும்.
உறவுமுறை
with sum_salary as
( select department_id, sum(salary) salary
from employee
group by department_id )
select department_id
from sum_salary a
where a.salary = ( select max(salary) from sum_salary )
செயல்பாட்டு
salarySum 'Максимальная зарплата' (Department d) =
GROUP SUM salary(Employee e) IF department(e) = d;
maxSalarySum 'Максимальная зарплата отделов' () =
GROUP MAX salarySum(Department d);
SELECT Department d WHERE salarySum(d) = maxSalarySum();
மற்றொன்றிலிருந்து மிகவும் சிக்கலான பணிகளுக்கு செல்லலாம்
சிக்கல் 2.1
1997 இல் எந்த விற்பனையாளர்கள் 30 யூனிட்களுக்கு மேல் தயாரிப்பு எண். 1 ஐ விற்றார்கள்?
டொமைன் லாஜிக் (ஆர்.டி.பி.எம்.எஸ்ஸில் முன்பு போலவே நாங்கள் அறிவிப்பைத் தவிர்க்கிறோம்):
CLASS Employee 'Продавец';
lastName 'Фамилия' = DATA STRING[100] (Employee);
CLASS Product 'Продукт';
id = DATA INTEGER (Product);
name = DATA STRING[100] (Product);
CLASS Order 'Заказ';
date = DATA DATE (Order);
employee = DATA Employee (Order);
CLASS Detail 'Строка заказа';
order = DATA Order (Detail);
product = DATA Product (Detail);
quantity = DATA NUMERIC[10,5] (Detail);
உறவுமுறை
select LastName
from Employees as e
where (
select sum(od.Quantity)
from [Order Details] as od
where od.ProductID = 1 and od.OrderID in (
select o.OrderID
from Orders as o
where year(o.OrderDate) = 1997 and e.EmployeeID = o.EmployeeID)
) > 30
செயல்பாட்டு
sold (Employee e, INTEGER productId, INTEGER year) =
GROUP SUM quantity(OrderDetail d) IF
employee(order(d)) = e AND
id(product(d)) = productId AND
extractYear(date(order(d))) = year;
SELECT lastName(Employee e) WHERE sold(e, 1, 1997) > 30;
சிக்கல் 2.2
ஒவ்வொரு வாங்குபவருக்கும் (பெயர், குடும்பப்பெயர்), 1997 இல் வாங்குபவர் அதிக பணம் செலவழித்த இரண்டு பொருட்களை (பெயர்) கண்டுபிடிக்கவும்.
முந்தைய எடுத்துக்காட்டில் இருந்து டொமைன் தர்க்கத்தை விரிவுபடுத்துகிறோம்:
CLASS Customer 'Клиент';
contactName 'ФИО' = DATA STRING[100] (Customer);
customer = DATA Customer (Order);
unitPrice = DATA NUMERIC[14,2] (Detail);
discount = DATA NUMERIC[6,2] (Detail);
உறவுமுறை
SELECT ContactName, ProductName FROM (
SELECT c.ContactName, p.ProductName
, ROW_NUMBER() OVER (
PARTITION BY c.ContactName
ORDER BY SUM(od.Quantity * od.UnitPrice * (1 - od.Discount)) DESC
) AS RatingByAmt
FROM Customers c
JOIN Orders o ON o.CustomerID = c.CustomerID
JOIN [Order Details] od ON od.OrderID = o.OrderID
JOIN Products p ON p.ProductID = od.ProductID
WHERE YEAR(o.OrderDate) = 1997
GROUP BY c.ContactName, p.ProductName
) t
WHERE RatingByAmt < 3
செயல்பாட்டு
sum (Detail d) = quantity(d) * unitPrice(d) * (1 - discount(d));
bought 'Купил' (Customer c, Product p, INTEGER y) =
GROUP SUM sum(Detail d) IF
customer(order(d)) = c AND
product(d) = p AND
extractYear(date(order(d))) = y;
rating 'Рейтинг' (Customer c, Product p, INTEGER y) =
PARTITION SUM 1 ORDER DESC bought(c, p, y), p BY c, y;
SELECT contactName(Customer c), name(Product p) WHERE rating(c, p, 1997) < 3;
பகிர்வு ஆபரேட்டர் பின்வரும் கொள்கையின்படி செயல்படுகிறது: இது SUM (இங்கே 1), குறிப்பிட்ட குழுக்களுக்குள் (இங்கே வாடிக்கையாளர் மற்றும் ஆண்டு, ஆனால் எந்த வெளிப்பாடாகவும் இருக்கலாம்), ஆர்டரில் குறிப்பிடப்பட்டுள்ள வெளிப்பாடுகளின்படி குழுக்களுக்குள் வரிசைப்படுத்தப்பட்ட வெளிப்பாட்டைத் தொகுக்கிறது ( இங்கே வாங்கப்பட்டது, சமமாக இருந்தால், உள் தயாரிப்புக் குறியீட்டின் படி).
சிக்கல் 2.3
தற்போதைய ஆர்டர்களை நிறைவேற்ற சப்ளையர்களிடமிருந்து எத்தனை பொருட்களை ஆர்டர் செய்ய வேண்டும்.
டொமைன் தர்க்கத்தை மீண்டும் விரிவாக்குவோம்:
CLASS Supplier 'Поставщик';
companyName = DATA STRING[100] (Supplier);
supplier = DATA Supplier (Product);
unitsInStock 'Остаток на складе' = DATA NUMERIC[10,3] (Product);
reorderLevel 'Норма продажи' = DATA NUMERIC[10,3] (Product);
உறவுமுறை
select s.CompanyName, p.ProductName, sum(od.Quantity) + p.ReorderLevel — p.UnitsInStock as ToOrder
from Orders o
join [Order Details] od on o.OrderID = od.OrderID
join Products p on od.ProductID = p.ProductID
join Suppliers s on p.SupplierID = s.SupplierID
where o.ShippedDate is null
group by s.CompanyName, p.ProductName, p.UnitsInStock, p.ReorderLevel
having p.UnitsInStock < sum(od.Quantity) + p.ReorderLevel
செயல்பாட்டு
orderedNotShipped 'Заказано, но не отгружено' (Product p) =
GROUP SUM quantity(OrderDetail d) IF product(d) = p;
toOrder 'К заказу' (Product p) = orderedNotShipped(p) + reorderLevel(p) - unitsInStock(p);
SELECT companyName(supplier(Product p)), name(p), toOrder(p) WHERE toOrder(p) > 0;
ஒரு நட்சத்திரத்தில் சிக்கல்
கடைசி உதாரணம் தனிப்பட்ட முறையில் என்னிடமிருந்து. ஒரு சமூக வலைப்பின்னலின் தர்க்கம் உள்ளது. மக்கள் ஒருவருக்கொருவர் நண்பர்களாகவும் ஒருவரையொருவர் விரும்பவும் முடியும். செயல்பாட்டு தரவுத்தள கண்ணோட்டத்தில் இது போல் இருக்கும்:
CLASS Person;
likes = DATA BOOLEAN (Person, Person);
friends = DATA BOOLEAN (Person, Person);
நட்புக்கான சாத்தியமான வேட்பாளர்களைக் கண்டுபிடிப்பது அவசியம். இன்னும் முறைப்படி, A, B, C ஆகிய அனைத்து நபர்களையும் நீங்கள் கண்டுபிடிக்க வேண்டும், அதாவது A B உடன் நண்பர், மற்றும் B என்பது C உடன் நண்பர், A C ஐ விரும்புகிறது, ஆனால் A ஆனது C உடன் நட்பு இல்லை.
செயல்பாட்டு தரவுத்தள கண்ணோட்டத்தில், வினவல் இப்படி இருக்கும்:
SELECT Person a, Person b, Person c WHERE
likes(a, c) AND NOT friends(a, c) AND
friends(a, b) AND friends(b, c);
SQL இல் இந்த சிக்கலைத் தானே தீர்க்க வாசகர் ஊக்குவிக்கப்படுகிறார். நீங்கள் விரும்பும் நபர்களை விட மிகக் குறைவான நண்பர்கள் இருப்பதாகக் கருதப்படுகிறது. எனவே அவை தனித்தனி அட்டவணையில் உள்ளன. வெற்றியடைந்தால், இரண்டு நட்சத்திரங்களுடன் ஒரு பணியும் உள்ளது. அதில், நட்பு சமச்சீராக இல்லை. செயல்பாட்டு தரவுத்தளத்தில் இது இப்படி இருக்கும்:
SELECT Person a, Person b, Person c WHERE
likes(a, c) AND NOT friends(a, c) AND
(friends(a, b) OR friends(b, a)) AND
(friends(b, c) OR friends(c, b));
UPD: முதல் மற்றும் இரண்டாவது நட்சத்திரத்தில் உள்ள பிரச்சனைக்கான தீர்வு
SELECT
pl.PersonAID
,pf.PersonAID
,pff.PersonAID
FROM Persons AS p
--Лайки
JOIN PersonRelationShip AS pl ON pl.PersonAID = p.PersonID
AND pl.Relation = 'Like'
--Друзья
JOIN PersonRelationShip AS pf ON pf.PersonAID = p.PersonID
AND pf.Relation = 'Friend'
--Друзья Друзей
JOIN PersonRelationShip AS pff ON pff.PersonAID = pf.PersonBID
AND pff.PersonBID = pl.PersonBID
AND pff.Relation = 'Friend'
--Ещё не дружат
LEFT JOIN PersonRelationShip AS pnf ON pnf.PersonAID = p.PersonID
AND pnf.PersonBID = pff.PersonBID
AND pnf.Relation = 'Friend'
WHERE pnf.PersonAID IS NULL
;WITH PersonRelationShipCollapsed AS (
SELECT pl.PersonAID
,pl.PersonBID
,pl.Relation
FROM #PersonRelationShip AS pl
UNION
SELECT pl.PersonBID AS PersonAID
,pl.PersonAID AS PersonBID
,pl.Relation
FROM #PersonRelationShip AS pl
)
SELECT
pl.PersonAID
,pf.PersonBID
,pff.PersonBID
FROM #Persons AS p
--Лайки
JOIN PersonRelationShipCollapsed AS pl ON pl.PersonAID = p.PersonID
AND pl.Relation = 'Like'
--Друзья
JOIN PersonRelationShipCollapsed AS pf ON pf.PersonAID = p.PersonID
AND pf.Relation = 'Friend'
--Друзья Друзей
JOIN PersonRelationShipCollapsed AS pff ON pff.PersonAID = pf.PersonBID
AND pff.PersonBID = pl.PersonBID
AND pff.Relation = 'Friend'
--Ещё не дружат
LEFT JOIN PersonRelationShipCollapsed AS pnf ON pnf.PersonAID = p.PersonID
AND pnf.PersonBID = pff.PersonBID
AND pnf.Relation = 'Friend'
WHERE pnf.[PersonAID] IS NULL
முடிவுக்கு
கொடுக்கப்பட்ட மொழி தொடரியல் என்பது கொடுக்கப்பட்ட கருத்தை செயல்படுத்துவதற்கான விருப்பங்களில் ஒன்றாகும் என்பதை கவனத்தில் கொள்ள வேண்டும். SQL அடிப்படையாக எடுத்துக் கொள்ளப்பட்டது, மேலும் அது முடிந்தவரை ஒத்ததாக இருக்க வேண்டும் என்பதே குறிக்கோள். நிச்சயமாக, சிலருக்கு முக்கிய வார்த்தைகளின் பெயர்கள், சொல் பதிவேடுகள் போன்றவை பிடிக்காமல் போகலாம். இங்கே முக்கிய விஷயம் கருத்து தானே. விரும்பினால், நீங்கள் C++ மற்றும் Python இரண்டையும் ஒத்த தொடரியல் செய்யலாம்.
விவரிக்கப்பட்ட தரவுத்தள கருத்து, என் கருத்துப்படி, பின்வரும் நன்மைகளைக் கொண்டுள்ளது:
- எளிதாக்க. இது ஒப்பீட்டளவில் அகநிலை குறிகாட்டியாகும், இது எளிமையான நிகழ்வுகளில் தெளிவாக இல்லை. ஆனால் நீங்கள் மிகவும் சிக்கலான நிகழ்வுகளைப் பார்த்தால் (எடுத்துக்காட்டாக, நட்சத்திரக் குறியீடுகளுடன் உள்ள சிக்கல்கள்), பின்னர், என் கருத்துப்படி, அத்தகைய வினவல்களை எழுதுவது மிகவும் எளிதானது.
- Инкапсуляция. சில எடுத்துக்காட்டுகளில் நான் இடைநிலை செயல்பாடுகளை அறிவித்தேன் (உதாரணமாக, விற்கப்படும், வாங்கி முதலியன), அதிலிருந்து அடுத்தடுத்த செயல்பாடுகள் உருவாக்கப்பட்டன. சில செயல்பாடுகளின் தர்க்கத்தை, தேவைப்பட்டால், அவற்றைச் சார்ந்தவற்றின் தர்க்கத்தை மாற்றாமல் மாற்ற இது உங்களை அனுமதிக்கிறது. உதாரணமாக, நீங்கள் விற்பனை செய்யலாம் விற்கப்படும் முற்றிலும் வேறுபட்ட பொருட்களிலிருந்து கணக்கிடப்பட்டது, மீதமுள்ள தர்க்கம் மாறாது. ஆம், இதை CREATE VIEW ஐப் பயன்படுத்தி RDBMS இல் செயல்படுத்தலாம். ஆனால் எல்லா லாஜிக்கையும் இப்படி எழுதினால், அதிகம் படிக்கும்படியாக இருக்காது.
- சொற்பொருள் இடைவெளி இல்லை. அத்தகைய தரவுத்தளம் செயல்பாடுகள் மற்றும் வகுப்புகளில் (அட்டவணைகள் மற்றும் புலங்களுக்குப் பதிலாக) செயல்படுகிறது. கிளாசிக்கல் புரோகிராமிங்கைப் போலவே (ஒரு முறையானது அது சார்ந்த வகுப்பின் வடிவத்தில் முதல் அளவுருவுடன் கூடிய செயல்பாடு என்று நாம் கருதினால்). அதன்படி, உலகளாவிய நிரலாக்க மொழிகளுடன் "நண்பர்களை உருவாக்குவது" மிகவும் எளிதாக இருக்க வேண்டும். கூடுதலாக, இந்த கருத்து மிகவும் சிக்கலான செயல்பாட்டை செயல்படுத்த அனுமதிக்கிறது. எடுத்துக்காட்டாக, நீங்கள் ஆபரேட்டர்களை உட்பொதிக்கலாம்:
CONSTRAINT sold(Employee e, 1, 2019) > 100 IF name(e) = 'Петя' MESSAGE 'Что-то Петя продает слишком много одного товара в 2019 году';
- பரம்பரை மற்றும் பாலிமார்பிசம். ஒரு செயல்பாட்டு தரவுத்தளத்தில், நீங்கள் CLASS ClassP மூலம் பல பரம்பரையை அறிமுகப்படுத்தலாம்: Class1, Class2 கட்டுமானங்கள் மற்றும் பல பாலிமார்பிஸத்தை செயல்படுத்தலாம். எப்படி என்பதை எதிர்கால கட்டுரைகளில் எழுதுவேன்.
இது வெறும் கருத்தாக இருந்தாலும், அனைத்து செயல்பாட்டு தர்க்கங்களையும் தொடர்புடைய தர்க்கமாக மொழிபெயர்க்கும் சில செயலாக்கங்களை ஜாவாவில் ஏற்கனவே நாங்கள் பெற்றுள்ளோம். கூடுதலாக, பிரதிநிதித்துவங்களின் தர்க்கம் மற்றும் பல விஷயங்கள் அதனுடன் அழகாக இணைக்கப்பட்டுள்ளன, இதன் மூலம் நாம் முழுவதையும் பெறுகிறோம்
ஆதாரம்: www.habr.com