Таблицы:
CREATE TABLE "Employees" (
"Id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
"Name" TEXT NOT NULL,
"EnrollmentDate" INTEGER NOT NULL,
"BaseSalary" REAL NOT NULL,
"ChiefId" INTEGER,
"PositionId" INTEGER
)
CREATE TABLE "Position" (
"Id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
"PositionName" INTEGER NOT NULL,
"YearPercent" INTEGER NOT NULL,
"MaxYearPercent" INTEGER
)
Позиции данных:
INSERT INTO "main"."Position" ("Id", "PositionName", "YearPercent", "MaxYearPercent") VALUES ('1', 'Employee', '0.03', '0.3');
INSERT INTO "main"."Position" ("Id", "PositionName", "YearPercent", "MaxYearPercent") VALUES ('2', 'Manager', '0.05', '0.4');
INSERT INTO "main"."Position" ("Id", "PositionName", "YearPercent", "MaxYearPercent") VALUES ('3', 'Salesman', '0.01', '0.35');
Данные сотрудников:
INSERT INTO "main"."Employees" ("Id", "Name", "EnrollmentDate", "BaseSalary", "ChiefId", "PositionId") VALUES ('1', 'A', '2019-05-18', '10000.0', '5', '1');
INSERT INTO "main"."Employees" ("Id", "Name", "EnrollmentDate", "BaseSalary", "ChiefId", "PositionId") VALUES ('2', 'B', '2019-07-26', '10000.0', '5', '1');
INSERT INTO "main"."Employees" ("Id", "Name", "EnrollmentDate", "BaseSalary", "ChiefId", "PositionId") VALUES ('3', 'C', '1990-09-19', '15000.0', '12', '1');
INSERT INTO "main"."Employees" ("Id", "Name", "EnrollmentDate", "BaseSalary", "ChiefId", "PositionId") VALUES ('4', 'D', '2017-01-20', '12000.0', '6', '1');
INSERT INTO "main"."Employees" ("Id", "Name", "EnrollmentDate", "BaseSalary", "ChiefId", "PositionId") VALUES ('5', 'E', '2017-01-20', '12000.0', '', '2');
INSERT INTO "main"."Employees" ("Id", "Name", "EnrollmentDate", "BaseSalary", "ChiefId", "PositionId") VALUES ('6', 'F', '2016-01-20', '18000.0', '7', '2');
INSERT INTO "main"."Employees" ("Id", "Name", "EnrollmentDate", "BaseSalary", "ChiefId", "PositionId") VALUES ('7', 'G', '2015-05-15', '11500', '', '2');
INSERT INTO "main"."Employees" ("Id", "Name", "EnrollmentDate", "BaseSalary", "ChiefId", "PositionId") VALUES ('8', 'H', '2009-03-01', '12300', '7', '2');
INSERT INTO "main"."Employees" ("Id", "Name", "EnrollmentDate", "BaseSalary", "ChiefId", "PositionId") VALUES ('9', 'I', '2001-02-12', '14000', '', '3');
INSERT INTO "main"."Employees" ("Id", "Name", "EnrollmentDate", "BaseSalary", "ChiefId", "PositionId") VALUES ('10', 'G', '2013-05-20', '25000', '8', '3');
INSERT INTO "main"."Employees" ("Id", "Name", "EnrollmentDate", "BaseSalary", "ChiefId", "PositionId") VALUES ('11', 'K', '2019-07-26', '5000', '', '3');
INSERT INTO "main"."Employees" ("Id", "Name", "EnrollmentDate", "BaseSalary", "ChiefId", "PositionId") VALUES ('12', 'L', '2016-01-20', '2000', '', '3');
Весь вопрос звучит так: «Есть 3 группы сотрудников- Сотрудник , Менеджер и Продавец . Каждый сотрудник может быть начальником. Каждый сотрудник, кроме Сотрудник , может иметь подчиненных.
Заработная плата работника рассчитывается следующим образом:
- Сотрудник - BaseSalary + 3% за каждый год работы, но не более 30%
- Менеджер - BaseSalary + 5% за каждый год, но не более 40% + 0,5% окладов подчиненных на 1-м уровне иерархии
- Продавец - BaseSalary + 1% за каждый год, но не более 35% + 0,3% от зарплаты подчиненных по всей иерархии
Запрос: «Выберите всех сотрудников с их зарплатой за последние полгода (месяцы должны быть горизонтальными)».
Я пытался добиться этого с небольшими шагами. Прежде всего, я посчитал зарплаты без подотчетности. ординаты (странным образом, я думаю):
SELECT Name,
CASE
WHEN (SELECT CAST((strftime('%Y', date('now', '-1 month')) + strftime('%j', date('now', '-1 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)) * (SELECT YearPercent FROM Position WHERE Position.Id = Employees.PositionId) >= (SELECT MaxYearPercent FROM Position WHERE Position.Id = Employees.PositionId) THEN BaseSalary + BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = Employees.PositionId)
ELSE BaseSalary + BaseSalary * (SELECT CAST((strftime('%Y', date('now', '-1 month')) + strftime('%j', date('now', '-1 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)) * (SELECT YearPercent FROM Position WHERE Position.Id = Employees.PositionId)
END AS '1 month',
CASE
WHEN (SELECT CAST((strftime('%Y', date('now', '-2 month')) + strftime('%j', date('now', '-2 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)) * (SELECT YearPercent FROM Position WHERE Position.Id = Employees.PositionId) >= (SELECT MaxYearPercent FROM Position WHERE Position.Id = Employees.PositionId) THEN BaseSalary + BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = Employees.PositionId)
ELSE BaseSalary + BaseSalary * (SELECT CAST((strftime('%Y', date('now', '-2 month')) + strftime('%j', date('now', '-2 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)) * (SELECT YearPercent FROM Position WHERE Position.Id = Employees.PositionId)
END AS '2 month',
CASE
WHEN (SELECT CAST((strftime('%Y', date('now', '-3 month')) + strftime('%j', date('now', '-3 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)) * (SELECT YearPercent FROM Position WHERE Position.Id = Employees.PositionId) >= (SELECT MaxYearPercent FROM Position WHERE Position.Id = Employees.PositionId) THEN BaseSalary + BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = Employees.PositionId)
ELSE BaseSalary + BaseSalary * (SELECT CAST((strftime('%Y', date('now', '-3 month')) + strftime('%j', date('now', '-3 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)) * (SELECT YearPercent FROM Position WHERE Position.Id = Employees.PositionId)
END AS '3 month',
CASE
WHEN (SELECT CAST((strftime('%Y', date('now', '-4 month')) + strftime('%j', date('now', '-4 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)) * (SELECT YearPercent FROM Position WHERE Position.Id = Employees.PositionId) >= (SELECT MaxYearPercent FROM Position WHERE Position.Id = Employees.PositionId) THEN BaseSalary + BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = Employees.PositionId)
ELSE BaseSalary + BaseSalary * (SELECT CAST((strftime('%Y', date('now', '-4 month')) + strftime('%j', date('now', '-4 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)) * (SELECT YearPercent FROM Position WHERE Position.Id = Employees.PositionId)
END AS '4 month',
CASE
WHEN (SELECT CAST((strftime('%Y', date('now', '-5 month')) + strftime('%j', date('now', '-5 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)) * (SELECT YearPercent FROM Position WHERE Position.Id = Employees.PositionId) >= (SELECT MaxYearPercent FROM Position WHERE Position.Id = Employees.PositionId) THEN BaseSalary + BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = Employees.PositionId)
ELSE BaseSalary + BaseSalary * (SELECT CAST((strftime('%Y', date('now', '-5 month')) + strftime('%j', date('now', '-5 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)) * (SELECT YearPercent FROM Position WHERE Position.Id = Employees.PositionId)
END AS '5 month',
CASE
WHEN (SELECT CAST((strftime('%Y', date('now', '-6 month')) + strftime('%j', date('now', '-6 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)) * (SELECT YearPercent FROM Position WHERE Position.Id = Employees.PositionId) >= (SELECT MaxYearPercent FROM Position WHERE Position.Id = Employees.PositionId) THEN BaseSalary + BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = Employees.PositionId)
ELSE BaseSalary + BaseSalary * (SELECT CAST((strftime('%Y', date('now', '-6 month')) + strftime('%j', date('now', '-6 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)) * (SELECT YearPercent FROM Position WHERE Position.Id = Employees.PositionId)
END AS '6 month'
FROM Employees;
Затем я посчитал зарплаты менеджерам (1-й уровень иерархии подчиненных):
SELECT e.Name, SUM(s.BaseSalary)
FROM Employees e
JOIN Employees s on e.Id = s.ChiefId
GROUP BY e.Name;
Последний шаг, который я сделал, подсчитал зарплаты продавцу(вся иерархия):
WITH Subordinates (Id, ParentId) AS (
SELECT Id, Id as ParentId
FROM Employees
UNION ALL
SELECT e.Id, s.ParentId
FROM Employees e INNER JOIN Subordinates s ON (s.Id = e.ChiefId)
)
SELECT e.Name, sum(e1.BaseSalary)
FROM Subordinates s
JOIN Employees e on e.Id = s.ParentId
LEFT JOIN Employees e1 on e1.Id = s.Id and s.Id != s.ParentId
GROUP BY e.Name
ORDER BY e.Name;
Следующим шагом должно быть просто испечь, что в 1 запросе я застрял на этом (запрос просто не считает правильную зарплату сотрудников, и я понятия не имею, почему это так):
WITH M1DIF AS (
SELECT CAST((strftime('%Y', date('now', '-1 month')) + strftime('%j', date('now', '-1 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)
FROM Employees
),
M2DIF AS (
SELECT CAST((strftime('%Y', date('now', '-2 month')) + strftime('%j', date('now', '-2 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)
FROM Employees
),
M3DIF AS (
SELECT CAST((strftime('%Y', date('now', '-3 month')) + strftime('%j', date('now', '-3 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)
FROM Employees
),
M4DIF AS (
SELECT CAST((strftime('%Y', date('now', '-4 month')) + strftime('%j', date('now', '-4 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)
FROM Employees
),
M5DIF AS (
SELECT CAST((strftime('%Y', date('now', '-5 month')) + strftime('%j', date('now', '-5 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)
FROM Employees
),
M6DIF AS (
SELECT CAST((strftime('%Y', date('now', '-6 month')) + strftime('%j', date('now', '-6 month')) / 365.2422) - (strftime('%Y', EnrollmentDate) + strftime('%j', EnrollmentDate) / 365.2422) AS INT)
FROM Employees
)
SELECT e.Name,
CASE
WHEN (SELECT * FROM M1DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId) >= (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId)
THEN
CASE
WHEN e.PositionId = 1 THEN e.BaseSalary + e.BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId)
WHEN e.PositionId = 2 THEN e.BaseSalary + e.BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId) + (CASE WHEN (SELECT SUM(e1.BaseSalary) FROM Employees e1 WHERE e1.ChiefId = e.Id) IS NULL THEN 0 ELSE (SELECT SUM(e1.BaseSalary) FROM Employees e1 WHERE e1.ChiefId = e.Id) END) * 0.05
END
ELSE
CASE
WHEN e.PositionId = 1 THEN e.BaseSalary + e.BaseSalary * (SELECT * FROM M1DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId)
WHEN e.PositionId = 2 THEN e.BaseSalary + e.BaseSalary * (SELECT * FROM M1DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId) + (CASE WHEN (SELECT SUM(e1.BaseSalary) FROM Employees e1 WHERE e1.ChiefId = e.Id) IS NULL THEN 0 ELSE (SELECT SUM(e1.BaseSalary) FROM Employees e1 WHERE e1.ChiefId = e.Id) END) * 0.05
END
END AS '1 month',
CASE
WHEN (SELECT * FROM M2DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId) >= (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId)
THEN e.BaseSalary + e.BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId)
ELSE e.BaseSalary + e.BaseSalary * (SELECT * FROM M2DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId)
END AS '2 month',
CASE
WHEN (SELECT * FROM M3DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId) >= (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId)
THEN e.BaseSalary + e.BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId)
ELSE e.BaseSalary + e.BaseSalary * (SELECT * FROM M3DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId)
END AS '3 month',
CASE
WHEN (SELECT * FROM M4DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId) >= (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId)
THEN e.BaseSalary + e.BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId)
ELSE e.BaseSalary + e.BaseSalary * (SELECT * FROM M4DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId)
END AS '4 month',
CASE
WHEN (SELECT * FROM M5DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId) >= (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId)
THEN e.BaseSalary + e.BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId)
ELSE e.BaseSalary + e.BaseSalary * (SELECT * FROM M5DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId)
END AS '5 month',
CASE
WHEN (SELECT * FROM M6DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId) >= (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId)
THEN e.BaseSalary + e.BaseSalary * (SELECT MaxYearPercent FROM Position WHERE Position.Id = e.PositionId)
ELSE e.BaseSalary + e.BaseSalary * (SELECT * FROM M6DIF) * (SELECT YearPercent FROM Position WHERE Position.Id = e.PositionId)
END AS '6 month'
FROM Employees e;
PS Я очень новичок в SQL.
Редактировать: Понял, что было неправильное решение использовать оператор WITH.