DBMS feidhme

Is iad na DBMSanna coibhneasta, a úsáideann an teanga SQL, is mó a bhí i ndomhan na mbunachair shonraí le fada an lá. An oiread sin go dtugtar NoSQL ar na leaganacha atá ag teacht chun cinn. D'éirigh leo áit áirithe a bhaint amach dóibh féin sa mhargadh seo, ach níl DBMSanna coibhneasta ag dul chun bás, agus leanfar de bheith á n-úsáid go gníomhach chun a gcríocha.

San Airteagal seo ba mhaith liom cur síos a dhéanamh ar choincheap bunachar sonraí feidhme. Ar mhaithe le tuiscint níos fearr, déanfaidh mé é seo trí é a chur i gcomparáid leis an tsamhail choibhneasta clasaiceach. Úsáidfear fadhbanna ó thástálacha SQL éagsúla a fhaightear ar an Idirlíon mar shamplaí.

Réamhrá

Feidhmíonn bunachair shonraí choibhneasta ar tháblaí agus ar réimsí. I mbunachar sonraí feidhme, bainfear úsáid as ranganna agus feidhmeanna ina ionad sin, faoi seach. Léireofar réimse i dtábla le N eochracha mar fheidhm de pharaiméadair N. In ionad gaolta idir táblaí, úsáidfear feidhmeanna a fhilleann rudaí den aicme lena ndéantar an nasc. Bainfear úsáid as comhdhéanamh feidhme in ionad JOIN.

Sula mbogfaidh mé go díreach chuig na tascanna, déanfaidh mé cur síos ar an tasc a bhaineann le loighic fearainn. Le haghaidh DDL úsáidfidh mé comhréir PostgreSQL. Le haghaidh feidhme tá a chomhréir féin aige.

Táblaí agus réimsí

Réad Sku simplí le réimsí ainm agus praghsanna:

Gaolmhar

CREATE TABLE Sku
(
    id bigint NOT NULL,
    name character varying(100),
    price numeric(10,5),
    CONSTRAINT id_pkey PRIMARY KEY (id)
)

Feidhmiúil

CLASS Sku;
name = DATA STRING[100] (Sku);
price = DATA NUMERIC[10,5] (Sku);

Fógraímid beirt feidhmeanna, a thógann Sku paraiméadar amháin mar ionchur agus cineál primitive a thabhairt ar ais.

Glactar leis go mbeidh cód inmheánach éigin ag gach réad i DBMS feidhme a ghintear go huathoibríoch agus gur féidir rochtain a fháil air más gá.

Socróimid an praghas don táirge/siopa/soláthraí. Féadfaidh sé athrú le himeacht ama, mar sin cuirimis réimse ama leis an tábla. Ní dhéanfaidh mé táblaí le haghaidh eolairí a dhearbhú i mbunachar sonraí coibhneasta chun an cód a ghiorrú:

Gaolmhar

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)
)

Feidhmiúil

CLASS Sku;
CLASS Store;
CLASS Supplier;
dateTime = DATA DATETIME (Sku, Store, Supplier);
price = DATA NUMERIC[10,5] (Sku, Store, Supplier);

Innéacsanna

Mar shampla deireanach, tógfaimid innéacs ar na heochracha go léir agus an dáta ionas gur féidir linn an praghas a fháil go tapa ar feadh tréimhse ama ar leith.

Gaolmhar

CREATE INDEX prices_date
    ON prices
    (skuId, storeId, supplierId, dateTime)

Feidhmiúil

INDEX Sku sk, Store st, Supplier sp, dateTime(sk, st, sp);

tascanna

Let tús le fadhbanna réasúnta simplí a tógadh as an comhfhreagrach Airteagal ar Habr.

Ar dtús, déanaimis loighic an fhearainn a dhearbhú (don bhunachar sonraí coibhneasta déantar é seo go díreach san alt thuas).

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);

Tasc 1.1

Taispeáin liosta fostaithe a fhaigheann tuarastal níos mó ná tuarastal a maoirseora láithreach.

Gaolmhar

select a.*
from   employee a, employee b
where  b.id = a.chief_id
and    a.salary > b.salary

Feidhmiúil

SELECT name(Employee a) WHERE salary(a) > salary(chief(a));

Tasc 1.2

Déan liosta de na fostaithe a fhaigheann an t-uastuarastal ina Roinn

Gaolmhar

select a.*
from   employee a
where  a.salary = ( select max(salary) from employee b
                    where  b.department_id = a.department_id )

Feidhmiúil

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));

Is ionann an dá fheidhmiúchán. Don chéad chás, i mbunachar sonraí coibhneasta is féidir leat úsáid a bhaint as CREATE VIEW, a bheidh ar an mbealach céanna a ríomh ar dtús leis an tuarastal uasta do roinn ar leith ann. Sa mhéid seo a leanas, ar mhaithe le soiléireacht, úsáidfidh mé an chéad chás, ós rud é go léiríonn sé an réiteach níos fearr.

Tasc 1.3

Taispeáin liosta de na IDs roinn, líon na bhfostaithe i nach mó ná 3 daoine.

Gaolmhar

select department_id
from   employee
group  by department_id
having count(*) <= 3

Feidhmiúil

countEmployees 'Количество сотрудников' (Department d) = 
    GROUP SUM 1 IF department(Employee e) = d;
SELECT Department d WHERE countEmployees(d) <= 3;

Tasc 1.4

Taispeáin liosta fostaithe nach bhfuil bainisteoir ainmnithe ag obair sa roinn chéanna.

Gaolmhar

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

Feidhmiúil

SELECT name(Employee a) WHERE NOT (department(chief(a)) = department(a));

Tasc 1.5

Faigh liosta d’aitheantais na roinne le huastuarastal iomlán an fhostaí.

Gaolmhar

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 )

Feidhmiúil

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();

A ligean ar bogadh ar aghaidh go dtí tascanna níos casta ó eile Airteagal. Tá anailís mhionsonraithe ann ar conas an tasc seo a chur i bhfeidhm in MS SQL.

Tasc 2.1

Cé na díoltóirí a dhíol níos mó ná 1997 aonad de tháirge Uimh. 30 i 1?

Loighic fearainn (mar a rinneadh roimhe seo ar RDBMS ní dhéanaimid an dearbhú):

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);

Gaolmhar

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

Feidhmiúil

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;

Tasc 2.2

I gcás gach ceannaitheoir (ainm, sloinne), faigh an dá earra (ainm) ar ar chaith an ceannaitheoir an t-airgead is mó i 1997.

Leathnaímid loighic an fhearainn ón sampla roimhe seo:

CLASS Customer 'Клиент';
contactName 'ФИО' = DATA STRING[100] (Customer);

customer = DATA Customer (Order);

unitPrice = DATA NUMERIC[14,2] (Detail);
discount = DATA NUMERIC[6,2] (Detail);

Gaolmhar

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

Feidhmiúil

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;

Oibríonn an t-oibreoir PARTITION ar an bprionsabal seo a leanas: suimíonn sé an slonn a shonraítear tar éis SUM (anseo 1), laistigh de na grúpaí sonraithe (anseo Custaiméir agus Bliain, ach d'fhéadfadh a bheith ar aon abairt), sórtáil laistigh de na grúpaí de réir na habairtí a shonraítear san ORDÚ ( anseo ceannaithe, agus más comhionann, ansin de réir an chóid táirge inmheánaigh).

Tasc 2.3

Cé mhéad earraí is gá a ordú ó sholáthróirí chun orduithe reatha a chomhlíonadh.

Déanaimis loighic an fhearainn a leathnú arís:

CLASS Supplier 'Поставщик';
companyName = DATA STRING[100] (Supplier);

supplier = DATA Supplier (Product);

unitsInStock 'Остаток на складе' = DATA NUMERIC[10,3] (Product);
reorderLevel 'Норма продажи' = DATA NUMERIC[10,3] (Product);

Gaolmhar

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

Feidhmiúil

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;

Fadhb le réiltín

Agus tá an sampla deireanach uaimse go pearsanta. Tá an loighic líonra sóisialta. Is féidir le daoine a bheith ina gcairde lena chéile agus cosúil lena chéile. Ó thaobh bunachar sonraí feidhme de bheadh ​​cuma mar seo air:

CLASS Person;
likes = DATA BOOLEAN (Person, Person);
friends = DATA BOOLEAN (Person, Person);

Is gá iarrthóirí féideartha a aimsiú le haghaidh cairdeas. Ar bhonn níos foirmeálta, ní mór duit na daoine go léir A, B, C a aimsiú ionas go bhfuil A cairde le B, agus B cairde le C, is maith le A C, ach nach bhfuil A cairde le C.
Ó thaobh bunachar sonraí feidhme de, is mar seo a bheadh ​​an chuma ar an gceist:

SELECT Person a, Person b, Person c WHERE 
    likes(a, c) AND NOT friends(a, c) AND 
    friends(a, b) AND friends(b, c);

Spreagtar an léitheoir an fhadhb seo a réiteach in SQL leis féin. Glactar leis go bhfuil i bhfad níos lú cairde ná daoine a thaitníonn leat. Dá bhrí sin tá siad i dtáblaí ar leith. Má éiríonn leis, tá tasc le dhá réalta ann freisin. I sé, nach bhfuil cairdeas siméadrach. Ar bhunachar sonraí feidhme bheadh ​​cuma mar seo air:

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: réiteach ar an bhfadhb leis an gcéad agus an dara réiltín ó dss_calika:

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 

Conclúid

Ba chóir a thabhairt faoi deara nach bhfuil sa chomhréir teanga ach ceann amháin de na roghanna chun an coincheap tugtha a chur i bhfeidhm. Glacadh SQL mar bhunús, agus ba é an sprioc go mbeadh sé chomh cosúil agus ab fhéidir leis. Ar ndóigh, b’fhéidir nach dtaitníonn cuid acu le hainmneacha eochairfhocail, cláir focal, etc. Is é an rud is mó anseo an coincheap féin. Más mian leat, is féidir leat comhréir comhchosúil C ++ agus Python a dhéanamh.

Tá na buntáistí seo a leanas ag baint le coincheap an bhunachair shonraí a gcuirtear síos air, i mo thuairim:

  • Simplíocht. Is táscaire sách suibiachtúil é seo nach bhfuil soiléir i gcásanna simplí. Ach má fhéachann tú ar chásanna níos casta (mar shampla, fadhbanna le réiltíní), ansin, i mo thuairim, tá sé i bhfad níos éasca ceisteanna den sórt sin a scríobh.
  • Инкапсуляция. I roinnt samplaí dhearbhaigh mé feidhmeanna idirmheánacha (mar shampla, a dhíoltar, Cheannaigh etc.), ónar tógadh feidhmeanna ina dhiaidh sin. Ligeann sé seo duit loighic feidhmeanna áirithe a athrú, más gá, gan loighic na ndaoine atá ag brath orthu a athrú. Mar shampla, is féidir leat díolacháin a dhéanamh a dhíoltar a ríomh ó rudaí go hiomlán difriúil, cé nach mbeidh an chuid eile den loighic a athrú. Is féidir, is féidir é seo a chur i bhfeidhm i RDBMS ag baint úsáide as CREATE VIEW. Ach má scríobhtar an loighic ar fad ar an mbealach seo, ní bheidh cuma an-inléite air.
  • Gan aon bhearna shéimeantach. Feidhmíonn bunachar sonraí den sórt sin ar fheidhmeanna agus ar aicmí (in ionad táblaí agus réimsí). Díreach mar atá i ríomhchlárú clasaiceach (má ghlacaimid leis gur feidhm é modh leis an gcéad pharaiméadar i bhfoirm an aicme lena mbaineann sé). Dá réir sin, ba cheart go mbeadh sé i bhfad níos éasca “cairde a dhéanamh” le teangacha ríomhchlárúcháin uilíoch. Ina theannta sin, ceadaíonn an coincheap seo feidhmiúlacht i bhfad níos casta a chur i bhfeidhm. Mar shampla, is féidir leat oibreoirí a leabú mar:

    CONSTRAINT sold(Employee e, 1, 2019) > 100 IF name(e) = 'Петя' MESSAGE  'Что-то Петя продает слишком много одного товара в 2019 году';

  • Oidhreacht agus polymorphism. I mbunachar sonraí feidhme, is féidir leat oidhreacht iolrach a thabhairt isteach tríd an AICME AicmeP: Tógann Class1, Class2 il-ilmhoirfeas agus cuireann sé i bhfeidhm é. Is dócha go scríobhfaidh mé go díreach in ailt amach anseo.

Cé nach bhfuil anseo ach coincheap, tá roinnt cur chun feidhme againn cheana féin i Java a aistríonn an loighic fheidhmiúil go léir go loighic choibhneasta. Ina theannta sin, tá loighic na n-uiríll agus go leor rudaí eile ceangailte go hálainn leis, agus a bhuíochas sin a fháil againn ar fad ardán. Go bunúsach, úsáidimid an RDBMS (PostgreSQL amháin faoi láthair) mar “mheaisín fíorúil”. Uaireanta tagann fadhbanna leis an aistriúchán seo toisc nach bhfuil staitisticí áirithe ar eolas ag an FDBMS ag optamóir fiosrúcháin an RDBMS. Go teoiriciúil, is féidir córas bainistíochta bunachar sonraí a chur i bhfeidhm a úsáidfidh struchtúr áirithe mar stóráil, arna oiriúnú go sonrach le haghaidh loighic fheidhmiúil.

Foinse: will.com

Add a comment