MySQL JOIN получается из одной таблицы в виде массива JSON в одной строке - PullRequest
0 голосов
/ 16 июня 2019

Я строю простую систему AGILE (что-то похожее на trello), где у меня есть несколько таблиц: пользователи, проекты, карты и некоторые другие, но здесь они не имеют значения.Вот структура таблиц:

Пользователи:

enter image description here

Проекты:

enter image description here

И карточки:

enter image description here

Мне нужно выбрать все проекты, где пользователи связаны с владельцем_id или проектом, чей идентификаторнаходится в таблице участников, в которой находится пользователь. Так что для простоты мне нужно найти все проекты, которыми владеет пользователь и где он является участником.

Я делаю это так:

SELECT * FROM app_site_agile_project AS project  
 LEFT JOIN (SELECT ID, display_name FROM app_site_users) users ON users.ID = '1' 
 LEFT JOIN (SELECT * FROM app_site_agile_project_participants) participants ON participants.participant_project_id = project.project_id
WHERE project.owner_id = '1' OR participants.participant_id = '1'

Это возвращает то, что я хочу.Но мне также нужно получить все карты для каждого проекта.Поэтому, если я добавлю еще одно объединение здесь:

SELECT * FROM app_site_agile_project AS project  
 LEFT JOIN (SELECT ID, display_name FROM app_site_users) users ON users.ID = '1' 
 LEFT JOIN (SELECT * FROM app_site_agile_project_participants) participants ON participants.participant_project_id = project.project_id
 LEFT JOIN (SELECT * FROM app_site_agile_project_cards) cards ON cards.project_id = project.project_id
WHERE project.owner_id = '1' OR participants.participant_id = '1'

Возвращает карточки, но результат будет содержать столько строк, сколько карточек во всех проектах, и это не то, что я хочу.Однако я хочу иметь еще один столбец «карточка» для каждого результата проекта, который будет содержать все карточки в виде массива или массива json.Прямо сейчас я делаю второй запрос для каждого проекта, чтобы получить его.

ps Чтобы упростить вам воссоздание моей таблицы, я написал этот список запросов, просто запустите его в пустой базе данных, чтобы получитьточная копия моего

CREATE TABLE app_site_users
(
    ID BIGINT(20) UNSIGNED PRIMARY KEY NOT NULL AUTO_INCREMENT,
    display_name VARCHAR(255) NOT NULL DEFAULT 'Incognito',
    register_date DATETIME DEFAULT CURRENT_TIMESTAMP
);

INSERT INTO `app_site_users` (`ID`, `display_name`, `register_date`) VALUES (NULL, 'User 1', current_timestamp());
INSERT INTO `app_site_users` (`ID`, `display_name`, `register_date`) VALUES (NULL, 'User 2', current_timestamp());
INSERT INTO `app_site_users` (`ID`, `display_name`, `register_date`) VALUES (NULL, 'User 3', current_timestamp());
INSERT INTO `app_site_users` (`ID`, `display_name`, `register_date`) VALUES (NULL, 'User 4', current_timestamp());

CREATE TABLE app_site_agile_project
(
    project_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    owner_id BIGINT(20) UNSIGNED NOT NULL,
    creation_time DATETIME DEFAULT CURRENT_TIMESTAMP,
    project_name VARCHAR(255) NOT NULL,
    last_update INT NOT NULL DEFAULT UNIX_TIMESTAMP() 
    COMMENT 'must also be updated on any dependent card changes',
    FOREIGN KEY (owner_id) REFERENCES app_site_users (ID)
);

INSERT INTO `app_site_agile_project` (`project_id`, `owner_id`, `creation_time`, `project_name`) VALUES (NULL, '1', current_timestamp(), 'Some project 1');
INSERT INTO `app_site_agile_project` (`project_id`, `owner_id`, `creation_time`, `project_name`) VALUES (NULL, '1', current_timestamp(), 'Project 2');
INSERT INTO `app_site_agile_project` (`project_id`, `owner_id`, `creation_time`, `project_name`) VALUES (NULL, '2', current_timestamp(), 'Another project #3');

CREATE TABLE app_site_agile_project_participants
(
    unique_participant_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    participant_project_id INT NOT NULL DEFAULT 0,
    participant_id BIGINT(20) UNSIGNED NOT NULL, 
    participant_privilege INT NOT NULL DEFAULT 0,
    FOREIGN KEY (participant_project_id) REFERENCES app_site_agile_project (project_id),
    FOREIGN KEY (participant_id) REFERENCES app_site_users (ID)
);
INSERT INTO app_site_agile_project_participants (unique_participant_id, participant_project_id, participant_id, participant_privilege) VALUES (NULL, '1', '1', '0');
INSERT INTO app_site_agile_project_participants (unique_participant_id, participant_project_id, participant_id, participant_privilege) VALUES (NULL, '1', '3', '0');

CREATE TABLE app_site_agile_project_cards
(
    card_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    project_id INT NOT NULL DEFAULT 0,
    last_update INT NOT NULL DEFAULT UNIX_TIMESTAMP(),
    creation_time DATETIME DEFAULT CURRENT_TIMESTAMP,
    card_data JSON NOT NULL, 
    FOREIGN KEY (project_id) REFERENCES app_site_agile_project (project_id)
);
INSERT INTO app_site_agile_project_cards (card_id, card_data, creation_time, project_id, last_update) VALUES (NULL, '{"title": "Card 1"}', current_timestamp(), 1, UNIX_TIMESTAMP());
INSERT INTO app_site_agile_project_cards (card_id, card_data, creation_time, project_id, last_update) VALUES (NULL, '{"title": "Card 2"}', current_timestamp(), 1, UNIX_TIMESTAMP());

CREATE TABLE app_site_agile_project_specs
(
    spec_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    last_update INT NOT NULL DEFAULT UNIX_TIMESTAMP(), 
    project_id INT COMMENT '',
    spec_text TEXT NOT NULL,
    FOREIGN KEY (project_id) REFERENCES app_site_agile_project (project_id)
);
...