ಕ್ರಿಯಾತ್ಮಕ DBMS

ಡೇಟಾಬೇಸ್‌ಗಳ ಪ್ರಪಂಚವು ದೀರ್ಘಕಾಲದವರೆಗೆ 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

ಇಲಾಖೆಯ ID ಗಳ ಪಟ್ಟಿಯನ್ನು ಪ್ರದರ್ಶಿಸಿ, 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

ಗರಿಷ್ಠ ಒಟ್ಟು ಉದ್ಯೋಗಿ ವೇತನದೊಂದಿಗೆ ಇಲಾಖೆಯ ID ಗಳ ಪಟ್ಟಿಯನ್ನು ಹುಡುಕಿ.

ಸಂಬಂಧಿತ

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

ಇನ್ನೊಂದರಿಂದ ಹೆಚ್ಚು ಸಂಕೀರ್ಣವಾದ ಕಾರ್ಯಗಳಿಗೆ ಹೋಗೋಣ ಲೇಖನಗಳು. MS SQL ನಲ್ಲಿ ಈ ಕಾರ್ಯವನ್ನು ಹೇಗೆ ಕಾರ್ಯಗತಗೊಳಿಸುವುದು ಎಂಬುದರ ವಿವರವಾದ ವಿಶ್ಲೇಷಣೆಯನ್ನು ಇದು ಒಳಗೊಂಡಿದೆ.

ಕಾರ್ಯ 2.1

ಯಾವ ಮಾರಾಟಗಾರರು 1997 ರಲ್ಲಿ ಉತ್ಪನ್ನ ಸಂಖ್ಯೆ 30 ರ 1 ಯೂನಿಟ್‌ಗಳಿಗಿಂತ ಹೆಚ್ಚು ಮಾರಾಟ ಮಾಡಿದರು?

ಡೊಮೇನ್ ಲಾಜಿಕ್ (RDBMS ನಲ್ಲಿ ಮೊದಲಿನಂತೆ ನಾವು ಘೋಷಣೆಯನ್ನು ಬಿಟ್ಟುಬಿಡುತ್ತೇವೆ):

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

ಯುಪಿಡಿ: ಮೊದಲ ಮತ್ತು ಎರಡನೇ ನಕ್ಷತ್ರ ಚಿಹ್ನೆಯಿಂದ ಸಮಸ್ಯೆಗೆ ಪರಿಹಾರ dss_ಕಲಿಕಾ:

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 ರಚನೆಗಳು ಮತ್ತು ಬಹು ಬಹುರೂಪತೆಯನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಬಹುದು. ಮುಂದಿನ ಲೇಖನಗಳಲ್ಲಿ ನಾನು ಬಹುಶಃ ಹೇಗೆ ನಿಖರವಾಗಿ ಬರೆಯುತ್ತೇನೆ.

ಇದು ಕೇವಲ ಪರಿಕಲ್ಪನೆಯಾಗಿದ್ದರೂ ಸಹ, ನಾವು ಈಗಾಗಲೇ ಜಾವಾದಲ್ಲಿ ಕೆಲವು ಕಾರ್ಯಗತಗೊಳಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿದ್ದೇವೆ ಅದು ಎಲ್ಲಾ ಕ್ರಿಯಾತ್ಮಕ ತರ್ಕವನ್ನು ಸಂಬಂಧಿತ ತರ್ಕಕ್ಕೆ ಅನುವಾದಿಸುತ್ತದೆ. ಜೊತೆಗೆ, ಪ್ರಾತಿನಿಧ್ಯಗಳ ತರ್ಕ ಮತ್ತು ಇತರ ಬಹಳಷ್ಟು ವಿಷಯಗಳನ್ನು ಸುಂದರವಾಗಿ ಲಗತ್ತಿಸಲಾಗಿದೆ, ಅದಕ್ಕೆ ಧನ್ಯವಾದಗಳು ನಾವು ಸಂಪೂರ್ಣವನ್ನು ಪಡೆಯುತ್ತೇವೆ ವೇದಿಕೆ. ಮೂಲಭೂತವಾಗಿ, ನಾವು RDBMS ಅನ್ನು ಬಳಸುತ್ತೇವೆ (ಸದ್ಯಕ್ಕೆ PostgreSQL ಮಾತ್ರ) "ವರ್ಚುವಲ್ ಯಂತ್ರ". RDBMS ಪ್ರಶ್ನೆ ಆಪ್ಟಿಮೈಜರ್ FDBMS ಗೆ ತಿಳಿದಿರುವ ಕೆಲವು ಅಂಕಿಅಂಶಗಳನ್ನು ತಿಳಿದಿರದ ಕಾರಣ ಕೆಲವೊಮ್ಮೆ ಈ ಅನುವಾದದೊಂದಿಗೆ ಸಮಸ್ಯೆಗಳು ಉದ್ಭವಿಸುತ್ತವೆ. ಸಿದ್ಧಾಂತದಲ್ಲಿ, ನಿರ್ದಿಷ್ಟ ರಚನೆಯನ್ನು ಶೇಖರಣೆಯಾಗಿ ಬಳಸುವ ಡೇಟಾಬೇಸ್ ನಿರ್ವಹಣಾ ವ್ಯವಸ್ಥೆಯನ್ನು ಕಾರ್ಯಗತಗೊಳಿಸಲು ಸಾಧ್ಯವಿದೆ, ನಿರ್ದಿಷ್ಟವಾಗಿ ಕ್ರಿಯಾತ್ಮಕ ತರ್ಕಕ್ಕೆ ಅಳವಡಿಸಲಾಗಿದೆ.

ಮೂಲ: www.habr.com

ಕಾಮೆಂಟ್ ಅನ್ನು ಸೇರಿಸಿ