Как мне управлять двумя таблицами закрытия для одного ресурса в SQLite3 - PullRequest
0 голосов
/ 04 февраля 2019

Надеюсь, это не слишком специфично для SO.Я нахожу это опытом обучения.

На высоком уровне я пишу интерфейс JSON: API в базу данных sqlite3 для хранения комментариев пользователей.С помощью JSON: API в разделе included может быть указан плоский список ресурсов, где каждый ресурс предоставляет relationships, который может указывать на другие комментарии. Было бы естественно использовать таблицу закрытия для представления потоков комментариев и комментариев.

Я начал со следующего:

CREATE TABLE comments (
  id INTEGER PRIMARY KEY,
  author TEXT,
  body TEXT,
  created_at DATE,
  email TEXT,
  href TEXT,
  ip_address TEXT,
  post_id TEXT
);

CREATE TABLE comment_threads (
  parent_id INTEGER NOT NULL,
  child_id INTEGER NOT NULL,
  PRIMARY KEY (parent_id, child_id)
);

CREATE TABLE comment_likes (
  comment_id INTEGER NOT NULL,
  ip_address TEXT NOT NULL,
  PRIMARY KEY (comment_id, ip_address)
);

Я думал, что смогу выбрать комментарии по post_id, затем взять комментарии из таблицы comment_thread и построить плоский списоккомментарии для помещения в раздел included вывода JSON: API.

Проблема заключается в том, что это означает много SQL-запросов и ручную перестройку связей комментариев.Меня беспокоит то, что кажется несколько наивным выполнять несколько запросов SQL для каждого ресурса.

Как мне (или можно I) выполнить это в одном (или меньшем) SQL-выражении (ях)?

Мне удалось это сделать с помощью лайков комментариев, используя:

SELECT c.id,c.author,c.body,c.created_at,c.href,c.post_id,
       COUNT(cl.comment_id) AS likes
FROM comments AS c
JOIN comment_likes AS cl ON c.id == cl.comment_id
WHERE c.post_id == 'test'
ORDER BY c.created_at ASC;

Но я не уверен, как можно расширить это, чтобы таблица выглядела так:

| id | author | body            | created_at | href | post_id | likes | comments   |
|====|========|=================|============|======|=========|=======|============|
|  1 | Bob    | test comment    | 1990-12-17 |      | test    |     1 | array(2,3) |
|  2 | Jane   | test comment 2  | 1990-12-18 |      |         |     0 | array()    |
|  3 | Jill   | test comment 3  | 1990-12-19 |      |         |     0 | array(4,5) |
|  4 | Bortus | test comment 4  | 1990-12-20 |      |         |     2 | array()    |
|  5 | John   | test comment 5  | 1990-12-21 |      |         |     0 | array()    |

Возможно ли это вообще?

Пример данных

INSERT INTO comments VALUES (1,'Bob','test comment','1990-12-17','foo@example.com',NULL,'1.1.1.1','test');
INSERT INTO comments VALUES (2,'Jane','test comment 2','1990-12-18','foo2@example.com',NULL,'1.1.1.2',NULL);
INSERT INTO comments VALUES (3,'Jill','test comment 3','1990-12-19','foo3@example.com',NULL,'1.1.1.3',NULL);
INSERT INTO comments VALUES (4,'Bortus','test comment 4','1990-12-20','foo4@example.com',NULL,'1.1.1.4',NULL);
INSERT INTO comments VALUES (5,'John','test comment 5','1990-12-21','foo5@example.com',NULL,'1.1.1.5',NULL);
INSERT INTO comments VALUES (6,'Spock','test comment 6','1990-12-22','foo6@example.com',NULL,'1.1.1.6','test2');
INSERT INTO comments VALUES (7,'Jim','test comment 7','1990-12-23','foo7@example.com',NULL,'1.1.1.7',NULL);
INSERT INTO comments VALUES (8,'Beverly','test comment 8','1990-12-24','foo8@example.com',NULL,'1.1.1.8',NULL);
INSERT INTO comments VALUES (9,'Stacy','test comment 9','1990-12-25','foo9@example.com',NULL,'1.1.1.9',NULL);
INSERT INTO comments VALUES (10,'Alice','test comment 10','1990-12-26','foo10@example.com',NULL,'1.1.1.10',NULL);

INSERT INTO comment_threads VALUES (1, 2);
INSERT INTO comment_threads VALUES (1, 3);
INSERT INTO comment_threads VALUES (3, 4);
INSERT INTO comment_threads VALUES (3, 5);
INSERT INTO comment_threads VALUES (6, 7);
INSERT INTO comment_threads VALUES (7, 8);
INSERT INTO comment_threads VALUES (8, 9);
INSERT INTO comment_threads VALUES (9, 10);

INSERT INTO comment_likes VALUES (1, '1.1.1.1');
INSERT INTO comment_likes VALUES (4, '1.1.1.2');
INSERT INTO comment_likes VALUES (4, '1.1.1.5');
INSERT INTO comment_likes VALUES (6, '1.1.1.1');
INSERT INTO comment_likes VALUES (6, '1.1.1.4');
INSERT INTO comment_likes VALUES (8, '1.1.1.1');

1 Ответ

0 голосов
/ 05 февраля 2019

Это легко сделать в одном утверждении - вам просто нужна пара коррелированных подзапросов в значениях, которые выбираются для вычисления одинакового количества и столбцов списка дочерних комментариев.

Примечание: Поскольку выВ любом случае, превратив это в JSON, следующий файл использует массив JSON для столбца комментариев, чтобы сохранить шаг, используя расширение JSON1 .Если ваша настройка sqlite не была скомпилирована с этим включенным, вы можете сделать нечто подобное с group_concat () .

SELECT id, author, body, created_at, href, post_id
     , (SELECT count(*) FROM comment_likes AS l WHERE c.id = l.comment_id) AS likes
     , (SELECT json_group_array(t.child_id) FROM comment_threads AS t WHERE c.id = t.parent_id) AS comments
FROM comments AS c
ORDER BY created_at;

производит

id          author      body          created_at  href        post_id     likes       comments  
----------  ----------  ------------  ----------  ----------  ----------  ----------  ----------
1           Bob         test comment  1990-12-17              test        1           [2,3]     
2           Jane        test comment  1990-12-18                          0           []        
3           Jill        test comment  1990-12-19                          0           [4,5]     
4           Bortus      test comment  1990-12-20                          2           []        
5           John        test comment  1990-12-21                          0           []        
6           Spock       test comment  1990-12-22              test2       2           [7]       
7           Jim         test comment  1990-12-23                          0           [8]       
8           Beverly     test comment  1990-12-24                          1           [9]       
9           Stacy       test comment  1990-12-25                          0           [10]      
10          Alice       test comment  1990-12-26                          0           []       

Изменить: Если вы хотите просто комментарий с конкретным post_id и его ветку ответов вместо каждого комментария, рекурсивные CTE вступают в игру:

WITH one_thread AS
 (SELECT id, author, body, created_at, href, post_id FROM comments WHERE post_id = 'test'
  UNION ALL
  SELECT c.id, c.author, c.body, c.created_at, c.href, c.post_id
  FROM one_thread AS o
  JOIN comment_threads AS t ON o.id = t.parent_id
  JOIN comments AS c ON t.child_id = c.id)
SELECT id, author, body, created_at, href, post_id
     , (SELECT count(*) FROM comment_likes AS l WHERE c.id = l.comment_id) AS likes
     , (SELECT json_group_array(t.child_id) FROM comment_threads AS t WHERE c.id = t.parent_id) AS comments
FROM one_thread AS c
ORDER BY created_at;

Это дает только

id          author      body          created_at  href        post_id     likes       comments  
----------  ----------  ------------  ----------  ----------  ----------  ----------  ----------
1           Bob         test comment  1990-12-17              test        1           [2,3]     
2           Jane        test comment  1990-12-18                          0           []        
3           Jill        test comment  1990-12-19                          0           [4,5]     
4           Bortus      test comment  1990-12-20                          2           []        
5           John        test comment  1990-12-21                          0           []  
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...