Базы данных SQL - все о моделировании отношений между данными, и для этого существуют хорошо разработанные способы. В этом случае у вас есть много пользователей, каждый из которых может иметь много навыков, - много ко многим . Способ моделирования этого известен под многими именами , но я предпочитаю соединительную таблицу . По сути, вместо таблицы со столбцом для каждого навыка и строкой для каждого пользователя, есть таблица из (skill id, user id)
пар со строкой для каждой конкретной комбинации. Если у пользователя нет навыка, строка с этой конкретной комбинацией не существует.
Настройка некоторых примеров таблиц из ваших данных, чтобы продемонстрировать идею:
CREATE TABLE SkillList(id INTEGER PRIMARY KEY, skill TEXT);
INSERT INTO SkillList VALUES
(1, 'Skill 1'), (2, 'Skill 2'), (3, 'Skill 3'), (4, 'Skill 4'), (5, 'Skill 5');
CREATE TABLE Attendance(id INTEGER PRIMARY KEY, username TEXT UNIQUE
, site TEXT, shift Text, SUN INTEGER, MON INTEGER
, TUE INTEGER, WED INTEGER, THU INTEGER, FRI INTEGER
, SAT INTEGER);
INSERT INTO Attendance VALUES
(1, 'Steve', 'Bldg1', 'Night', 1, 1, 1, 1, 1, 0, 0),
(2, 'Dave', 'Bldg1', 'Night', 1, 1, 0, 0, 1, 1, 1),
(3, 'Jack', 'Bldg2', 'Day', 1, 1, 1, 0, 0, 1, 1),
(4, 'Jacob', 'Bldg1', 'Night', 1, 0, 0, 1, 1, 1, 1);
CREATE TABLE SkillsAvailable(skill_id INTEGER REFERENCES SkillList(id)
, user_id INTEGER REFERENCES Attendance(id)
, PRIMARY KEY(skill_id, user_id)) WITHOUT ROWID;
INSERT INTO SkillsAvailable VALUES
(1, 1), (1, 2), (1, 3), (1, 4),
(2, 1), (2, 3), (2, 4),
(3, 1), (3, 2),
(4, 1);
позволит вам объединить таблицы SkillList
и Attendance
вместе, поставив SkillsAvailable
в середине:
SELECT sl.skill AS "Skill Name"
, ifnull(sum(a.SUN), 0) AS SUN
, ifnull(sum(a.MON), 0) AS MON
, ifnull(sum(a.TUE), 0) AS TUE
, ifnull(sum(a.WED), 0) AS WED
, ifnull(sum(a.THU), 0) AS THU
, ifnull(sum(a.FRI), 0) AS FRI
, ifnull(sum(a.SAT), 0) AS SAT
FROM SkillList AS sl
LEFT OUTER JOIN SkillsAvailable AS sa ON sl.id = sa.skill_id
LEFT OUTER JOIN Attendance AS a ON sa.user_id = a.id
GROUP BY sl.id
ORDER BY sl.skill;
Внешние объединения используются для того, чтобы навыки, которые никем не использовались, по-прежнему отображались в результатах:
Skill Name SUN MON TUE WED THU FRI SAT
---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
Skill 1 4 3 2 2 3 3 3
Skill 2 3 2 2 2 2 2 2
Skill 3 2 2 1 1 2 1 1
Skill 4 1 1 1 1 1 0 0
Skill 5 0 0 0 0 0 0 0
Помимо усложнения такого рода расчетов, у вашей текущей схемы базы данных есть и другие проблемы с таблицей "Skills Available"
- добавление нового навыка означает добавление нового столбца, удаление навыка, который вам не нужен, означает либо удаление этого столбца - очень запутанный процесс в sqlite - или когда неиспользуемые зависают, тратя немного места. Это делает для хрупкого, над сложным дизайном. Лучше играть на сильных сторонах реляционных баз данных.